在AbstractQueuedSynchronizer
类中维护了一个用volatile
修饰的state
状态,而这个状态有如下的两种修改方法:
state
的set
方法:
protected final void setState(int newState) {
state = newState;
}
CAS
方法:
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
那么,我的疑问来了,不是说volatile
修饰的变量在多线程的单操作中,能够保证其写后读的可见性,即能保证线程安全,为什么还提供了CAS
操作能保证线程安全呢?还是我的理解有问题呢?谢谢各位大牛了!
이는 충돌이 아닙니다. setState는 단지 쓰기 작업이며 원래 상태에 관심이 없습니다. 예를 들어 상태는 원래 0이었습니다. 스레드 1과 스레드 2는 각각 값을 1로 설정했습니다. 그런 다음 스레드 2는 이를 2로 설정할 계획이며 이는 성공할 수 있습니다. 상태가 이미 1이고 스레드 2도 이를 알고 있지만 스레드 2는 이를 2로 설정하기만 하면 됩니다. 다음 방법은 작동하지 않습니다.
네, 이해에 문제가 있습니다.
가시성을 보장할 수 있다고 해서 스레드 안전성이 보장되는 것은 아닙니다. 가시성과 스레드 안전성은 동일한 개념이 아닙니다.
카스 작업은 여러 개의 작은 작업으로 나눌 수 있습니다
기대 변수와 상태 변수의 현재 값을 비교합니다. 동일하면 2단계로 진행하고, 다르면 메서드가 종료됩니다.
상태 업데이트에 값 할당
이 두 작업이 여러 스레드에서 동시에 호출되면 스레드 안전 문제가 발생합니다.
여기서 cas 메소드는 원자적 연산인 CPU의 cas 명령을 사용합니다. 동시성 문제를 피할 수 있습니다.
요약:
원래 값에 의존하지 않는다면 set을 사용해도 됩니다
원래 값에 의존하는 경우 CAS를 사용하여 설정할 수 있습니다. 이것은 그 자체로 낙관적인 잠금입니다.