답변:
여러 스레드가 부울을 확인하고 변경해야하는 경우 예를 들면 다음과 같습니다.
if (!initialized) {
initialize();
initialized = true;
}
스레드 안전하지 않습니다. 다음을 사용하여 문제를 해결할 수 있습니다 AtomicBoolean
.
if (atomicInitialized.compareAndSet(false, true)) {
initialize();
}
true
시점 initialize()
을 볼 수 있습니다 . 따라서 다른 스레드가 완료를 신경 쓰지 않는 경우에만 작동합니다 initialize()
.
initialized
하나의 스레드 만 initialize()
메소드 를 호출하도록 보장하는 데 사용되는 경우 실제로 유효한 실제 예제라고 생각합니다 . 분명히 initialized
그 초기화를 의미하지 않는다 진실되고하는 것은 확실히 때문에,이 경우 완료 어쩌면 약간 다른 용어보다 잘 될 것입니다. 다시, 그것은 그것이 사용되는 것에 달려 있습니다.
volatile boolean
와 같지 않습니다 AtomicBoolean
.
synchronized
당신이 더 이상을 필요로하는 경우에 블록 AtomicBoolean
단지를 volatile boolean
. ( if(! this.initialized) { synchronized(this) { if(! this.initialized) { initialize(); this.initialized = true; } } }
하나의 스레드 만 호출 initialize
하고 다른 모든 스레드는 스레드 initialized
가 표시 될 때까지 기다립니다 volatile
.)
여기 내가 작성한 참고 사항 ( Brian Goetz book )이 도움이 될 것입니다.
AtomicXXX 수업
비 차단 비교 및 스왑 구현 제공
하드웨어 (Intel의 CMPXCHG 명령)가 제공하는 지원을 활용합니다. 이러한 원자 적 동시성 API를 사용하는 코드를 통해 많은 스레드가 실행중인 경우 객체 레벨 모니터 / 동기화를 사용하는 코드보다 훨씬 확장 성이 뛰어납니다. Java의 동기화 메커니즘으로 인해 코드 대기 상태가되므로 중요한 섹션을 통해 많은 스레드가 실행되는 경우 동기화 메커니즘 자체 (대기, 알림 등)를 관리하는 데 상당한 양의 CPU 시간이 소요됩니다. 새로운 API는 하드웨어 수준 구성 (원자 변수)을 사용하고 스레드 안전을 구현하기 위해 사용 가능한 알고리즘을 대기 및 잠금 상태로 만들기 때문에 동기화를 관리하는 대신 "작업 수행"에 훨씬 많은 CPU 시간이 소비됩니다.
더 나은 처리량을 제공 할뿐만 아니라 교착 상태 및 우선 순위 반전과 같은 작동 문제에 대한 저항력도 향상됩니다.
원자 부울을 사용할 수있는 두 가지 주요 이유가 있습니다. 먼저 변경 가능하므로 참조로 전달하고 예를 들어 부울 자체와 관련된 값을 변경할 수 있습니다.
public final class MyThreadSafeClass{
private AtomicBoolean myBoolean = new AtomicBoolean(false);
private SomeThreadSafeObject someObject = new SomeThreadSafeObject();
public boolean doSomething(){
someObject.doSomeWork(myBoolean);
return myBoolean.get(); //will return true
}
}
그리고 someObject 클래스에서
public final class SomeThreadSafeObject{
public void doSomeWork(AtomicBoolean b){
b.set(true);
}
}
더 중요한 것은 스레드가 안전하고 클래스를 유지 관리하는 개발자 에게이 변수가 수정되어 여러 스레드에서 읽힐 것으로 예상 될 수 있음을 나타낼 수 있습니다. AtomicBoolean을 사용하지 않는 경우 사용중인 부울 변수를 휘발성으로 선언하거나 필드의 읽기 및 쓰기 주위에서 동기화하여 부울 변수를 동기화해야합니다.
이 AtomicBoolean
클래스는 원자 적으로 업데이트 할 수있는 부울 값을 제공합니다. 부울 변수에 액세스하는 여러 스레드가있는 경우이를 사용하십시오.
java.util.concurrent.atomic의 패키지 개요 당신이 패키지의 클래스가 할 때 그들을 사용하는 것의 좋은 높은 수준의 설명을 제공합니다. 또한 Brian Goetz의 Java Concurrency in Practice 책을 추천합니다 .
패키지 설명 에서 발췌
패키지 java.util.concurrent.atomic 설명 : 단일 변수에서 잠금없는 스레드 안전 프로그래밍을 지원하는 작은 클래스의 툴킷 [...]
이러한 방법의 사양은 구현이 최신 프로세서에서 사용할 수있는 효율적인 기계 수준의 원자 명령어를 사용할 수 있도록합니다. [...]
AtomicBoolean, AtomicInteger, AtomicLong 및 AtomicReference 클래스의 인스턴스는 각각 해당 유형의 단일 변수에 대한 액세스 및 업데이트를 제공합니다. [...]
원자의 접근 및 업데이트에 대한 메모리 효과는 일반적으로 휘발성 물질에 대한 규칙을 따릅니다.
- get은 휘발성 변수를 읽는 메모리 효과가 있습니다.
- set은 휘발성 변수를 작성 (할당)하는 메모리 효과가 있습니다.
- weakCompareAndSet는 원자 적으로 변수를 읽고 조건부로 쓰고 해당 변수에 대한 다른 메모리 작업과 관련하여 정렬되지만 일반적인 비 휘발성 메모리 작업으로 작동합니다.
- compareAndSet 및 getAndIncrement와 같은 다른 모든 읽기 및 업데이트 작업은 휘발성 변수를 읽고 쓰는 데 메모리 효과가 있습니다.
volatile boolean
대AtomicBoolean
: stackoverflow.com/questions/3786825/...