java - AQS中源码疑问
巴扎黑
巴扎黑 2017-04-18 10:48:23
0
3
565

AbstractQueuedSynchronizer类中维护了一个用volatile修饰的state状态,而这个状态有如下的两种修改方法:

  • stateset方法:

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操作能保证线程安全呢?还是我的理解有问题呢?谢谢各位大牛了!

巴扎黑
巴扎黑

全部回覆(3)
小葫芦

不衝突吧,setState只是一個寫操作,並沒有管原來的state,比如state原本是0,線程1和線程2分別讀取了這個值0,線程1把它set成1,然後線程2打算把它set成2,是可以成功的,儘管state已經是1了,而且線程2也知道,但是無所謂,線程2只是把它set成2。下面那個方法就不會了吧。

左手右手慢动作

是的,你的理解有問題。

不是說volatile修飾的變數在多執行緒的單一操作中,能夠保證其寫後讀的可見性,即能保證執行緒安全

能夠保證可見性,不代表可以保證執行緒安全。可見性跟線程安全不是同一個概念。

cas操作,可以分割成幾個小操作

  1. 比較 expect 和 state 變數目前的值,如果相同,繼續2,如果不同,方法結束。

  2. 為 state 賦值 update

這兩個操作,如果是多執行緒並發調用,是會有執行緒安全問題的。
這裡的 cas 方法利用了 cpu 的 cas 指令,這個指令是原子操作。可以避免併發問題。

Peter_Zhu

簡而言之:

  1. 不依賴原始值的可以使用set

  2. 依賴原始值的可以使用cas去設定。本身這是個樂觀鎖。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!