在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
操作能保证线程安全呢?还是我的理解有问题呢?谢谢各位大牛了!
It’s not a conflict, right? setState is just a write operation and does not care about the original state. For example, the state was originally 0. Thread 1 and thread 2 read the value 0 respectively. Thread 1 set it to 1, and then thread 2 decided to Setting it to 2 can be successful, although the state is already 1, and thread 2 also knows it, but it doesn't matter, thread 2 just sets it to 2. The following method will not work.
Yes, there is a problem with your understanding.
Being able to guarantee visibility does not mean that thread safety can be guaranteed. Visibility and thread safety are not the same concept.
cas operation can be divided into several small operations
Compare the current values of expect and state variables. If they are the same, continue with step 2. If they are different, the method ends.
Assign value to state update
If these two operations are called concurrently by multiple threads, there will be thread safety issues.
The cas method here uses the cas instruction of the CPU, which is an atomic operation. Concurrency issues can be avoided.
In short:
If you don’t rely on the original value, you can use set
If you rely on the original value, you can use cas to set it. This is an optimistic lock in itself.