자바 다 중 스 레 드 3 대 핵심
원자 성
Java
의 원자 성 은 데이터베이스 업무 의 원자 성과 차이 가 많 지 않 고 한 작업 에서 모두 성공 하거나 실패 합 니 다.JMM
은 기본 적 인 원자 성 을 보장 할 뿐 i++
과 같은 조작 은 원자 조작 인 것 처럼 보이 지만 사실은 다음 과 같다.이 세 가지 조작 을 하기 때문에
i++
과 같은 원자 조작 을 실현 하려 면 synchronized
또는 lock
으로 잠 금 처 리 를 해 야 한다.기초 류 의 자체 증가 조작 이 라면
AtomicInteger
과 같은 원자 류 를 사용 하여 실현 할 수 있다.그 중에서 가장 많이 사용 하 는 방법 은
CPU
원자 방식 으로 증가 하 는 것 이다.원본 코드 는 다음 과 같 습 니 다.public final long incrementAndGet() {
for (;;) {
long current = get();
long next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
우선 현재 값 을 얻 은 다음+1 증가 합 니 다.이 어 가장 핵심 적 인
CAS
으로 원자 업 데 이 트 를 진행 했다.public final boolean compareAndSet(long expect, long update) {
return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
}
그 논 리 는 현재 값 이 업데이트 되 었 는 지,
incrementAndGet()
과 같은 지 판단 하 는 것 이다.만약 에 업데이트 되 지 않 았 다 는 것 을 설명 한 다음 에 현재 값 을 compareAndSet()
으로 업데이트 하고 그렇지 않 으 면 current
으로 돌아 가 업데이트 가 성공 할 때 까지 순환 하 는 것 이다.그리고 그 중의
next
방법 도 매우 관건 적 이다.현재 의 값 을 되 돌려 주 고 현재 값 은 false
키워드 로 수식 하여 메모리 의 가시 성 을 확보 했다. private volatile int value;
가시 성
현대 컴퓨터 에 서 는
get()
이 메 인 메모리 에서 데 이 터 를 직접 읽 는 효율 이 높 지 않 기 때문에 모두 대응 하 는 volatile
캐 시 입 니 다.먼저 메 인 메모리 의 데 이 터 를 캐 시 에 읽 고 스 레 드 가 데 이 터 를 수정 한 후에 캐 시 에 먼저 업데이트 한 후에 야 메 인 메모리 로 업 데 이 트 됩 니 다.이 때 메 인 메모리 의 다른 스 레 드 에 데 이 터 를 업데이트 하지 않 았 다 면 이 때 읽 는 것 은 수정 전의 데이터 입 니 다.위의 그림 과 같다.
CPU
키 워드 는 메모리 의 가시 성 을 확보 하 는 데 사 용 됩 니 다.스 레 드 A 가 volatile 수식 변 수 를 업데이트 하면 메 인 스 레 드 로 바로 갱신 되 고 나머지 캐 시 에 있 는 이 변수의 값 을 비 워 서 나머지 스 레 드 는 메 인 메모리 에서 최신 값 만 읽 을 수 있 습 니 다.CPU
키 워드 를 사용 하여 수식 하 는 변 수 는 읽 을 때마다 최신 데 이 터 를 얻 을 수 있 습 니 다.어떤 스 레 드 가 이 변수 에 대한 수정 이 든 바로 메 인 메모리 로 갱 신 됩 니 다.volatile
과 자 물 쇠 를 추가 해도 가시 성 을 확보 할 수 있다.실현 원 리 는 자 물 쇠 를 풀 기 전에 나머지 스 레 드 는 이 공유 변 수 를 방문 하지 못 하 는 것 이다.하지만 volatile
에 비해 씀 씀 이 가 크다.순서 성
다음 코드:
int a = 100 ; //1
int b = 200 ; //2
int c = a + b ; //3
정상 적 인 상황 에서 의 집행 순 서 는
synchronized
일 것 이다.그러나 때로는 volatile
이 전체적인 효율 을 높이 기 위해 지령 정렬 을 해서 집행 하 는 순서 가 1>>2>>3
일 수도 있다.그러나 JVM
도 모든 것 을 재 배열 할 수 없고 최종 결과 와 코드 순서 집행 결과 가 일치 하도록 보장 하 는 상황 에서 재 배열 이 가능 하 다.단일 스 레 드 에 다시 배열 하 는 데 는 문제 가 없 지만 다 중 스 레 드 에 서 는 데이터 가 일치 하지 않 는 문제 가 발생 할 수 있 습 니 다.
자바 에 서 는
2>>1>>3
을 사용 하여 순서 성 을 확보 할 수 있 고 JVM
도 질서 성 을 확보 할 수 있 으 며 원자 성 을 확보 하 는 방식 과 마찬가지 로 같은 시간 에 하나의 스 레 드 만 방문 하여 이 루어 질 수 있다.volatile
키워드 명시 적 보증 순 서 를 제외 하고 synchronized lock
은 volatile
원칙 을 통 해 암시 적 인 보증 순서 성 을 가진다.그 중 하 나 는
JVM
키워드 에 적용 되 는 것 으로 happen-before
키 워드 를 대상 으로 하 는 쓰기 동작 은 읽 기 동작 전에 읽 은 값 이 최신 일 것 이다.volatile 의 응용
이중 검사 자물쇠 의 단일 모드
volatile
으로 이중 검사 잠 금 의 단일 모드 를 실현 할 수 있 습 니 다. public class Singleton {
private static volatile Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
이곳 의
volatile
키 워드 는 주로 명령 의 재 배열 을 방지 하기 위 한 것 이다.만약 에 volatile
,volatile
을 사용 하지 않 으 면 이 코드 는 사실은 세 단계 로 나 뉜 다.volatile
대상 을 분 배 된 메모리 주 소 를 가리킨다.(3) 게다가
singleton = new Singleton();
은 상기 세 단계 의 조작 순 서 를 집행 하기 위해 서 이 며,반대로 세 번 째 단계 가 두 번 째 단계 이전에 실 행 될 경우 특정한 스 레 드 가 받 은 단일 대상 이 초기 화 되 지 않 아 사용 오류 가 발생 할 수 있다.스 레 드 정지 표시 제어
private volatile boolean flag ;
private void run(){
new Thread(new Runnable() {
@Override
public void run() {
doSomeThing();
}
});
}
private void stop(){
flag = false ;
}
여기 서 만약 volatile 로 flag 를 수식 하지 않 았 다 면,그 중의 한 라인 이
singleton
방법 으로 flag 의 값 을 수정 하여 주 메모리 에 바로 갱신 하지 않 았 을 수도 있 고,이 순환 이 즉각 멈 추 지 않 았 을 수도 있다.이곳 에서 주로 이용 하 는 것 은
volatile
의 메모리 가시 성 이다.요약:-
stop()
키 워드 는 가시 성,순서 성 만 보장 할 수 있 고 원자 성 을 보장 할 수 없습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JAVA 다 중 스 레 드 메커니즘 의 스 레 드 생 성target 을 실행 대상 으로 지정 한 name 을 이름 으로 하고 group 에서 참조 하 는 스 레 드 그룹의 일원 으로 새 Thread 대상 을 할당 합 니 다. 이 스 레 드 가 독립 된 Runnable 실...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.