volatile、synchronize關(guān)鍵字坝疼,Lock類的定義與特性

volatile關(guān)鍵字

定義:對(duì)該變量禁止使用CPU緩存搜贤,而從主內(nèi)存中讀寫
特性:
  1. 禁止編碼優(yōu)化(禁止指令重排序)
  2. 保證變量的線程可見(jiàn)性,即線程B對(duì)線程A的操作是可見(jiàn)的钝凶,即原則1 遵循h(huán)appens-before原則
  3. 不會(huì)對(duì)線程阻塞仪芒,而只是對(duì)變量的"讀或?qū)?保證原子性,但不對(duì)"讀并且寫"保證原子性耕陷〉嗝可以理解為有兩個(gè)鎖:讀鎖和寫鎖,但不可同時(shí)讀和寫哟沫,見(jiàn)increase方法饺蔑;故此時(shí)一寫多讀時(shí)可以保證數(shù)據(jù)一致。
    若要多寫多讀嗜诀,synchronize關(guān)鍵字或Lock類
    volatile static int inc = 0;

    public static void main(String[] args) {
        Runnable runnable = ()->{
            increase();
        };
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        for (int i = 0; i < 20; i++) {
            executorService.execute(runnable);
        }
        // 等待所有線程結(jié)束
        executorService.shutdown();
        System.out.println(inc);
    }

    private static /*synchronized*/ void increase() {
        for (int i = 0; i < 1000; i++) {
            // 如線程A執(zhí)行至256次內(nèi)存讀到256猾警,線程B已經(jīng)執(zhí)行完1000次寫入內(nèi)存1000,此時(shí)線程A第257次內(nèi)存讀到1000隆敢,繼續(xù)剩下的743次循環(huán)
            inc++; // inc = inc + 1 讀inc并且寫inc
        }
    }

19418
Process finished with exit code 0

happens-befores原則:

定義:前一個(gè)操作的結(jié)果對(duì)后續(xù)操作是可見(jiàn)的

共8條原則
主要為

  1. 順序性
  2. volatile原則
  3. 傳遞性
    ...
    見(jiàn)Java并發(fā)編程實(shí)戰(zhàn)
    java 8大happen-before原則超全面詳解

synchronize關(guān)鍵字

定義:Java中互斥鎖技術(shù)的實(shí)現(xiàn)
特性:
  1. 可修飾方法发皿,代碼塊
class X {
  // 修飾非靜態(tài)方法
  synchronized void foo() {
    // 臨界區(qū)
  }
  // 修飾靜態(tài)方法
  synchronized static void bar() {
    // 臨界區(qū)
  }
  // 修飾代碼塊
  Object obj = new Object();
  void baz() {
    synchronized(obj) {// lock()
      // 臨界區(qū)
    //unlock()
    }
  }
}
  1. 修飾static方法時(shí)拂蝎,實(shí)際鎖的是該類的.class對(duì)象穴墅;修飾非static方法時(shí),鎖的時(shí)該this對(duì)象
    注意:使用鎖synchronized要注意以哪個(gè)對(duì)象為鎖温自,和要保護(hù)的資源(臨界區(qū))封救,在同一個(gè)鎖下的臨界區(qū)是保證原子性的
class obj {
  synchronized(obj.class) static void foo1(){}
  // obj.class是單例的
  synchronized(this) void foo2(){}
  // this是可以new出多個(gè)的
}
  1. wait()、notify()捣作、notifyAll()只能在sychronized代碼塊中使用
sychronized(this){
  this.wait() // 此處釋放的鎖一定為this誉结,即鎖對(duì)象
  // 若鎖對(duì)象為targer,則為target.wait()
}

wait():釋放該互斥鎖券躁,同時(shí)該線程進(jìn)入等待隊(duì)列惩坑,使其他線程可以搶占該鎖 sleep()使線程阻塞,不會(huì)釋放鎖
notify(): 隨機(jī)通知等待隊(duì)列中的一個(gè)線程也拜,條件滿足以舒,可以執(zhí)行wait()之后代碼
使用notifyAll():通知隊(duì)列中所有線程,條件滿足

Lock接口

定義:Lock為concurrent.locks包下的一個(gè)接口慢哈,該locks包提供對(duì)線程鎖操作的方法蔓钟。
特性:

1.常用實(shí)現(xiàn)類:

        ReentrantLock lock = new ReentrantLock();   // 實(shí)現(xiàn)Lock接口
        ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();    // 實(shí)現(xiàn)ReadWriteLock,提供讀鎖或?qū)戞i
        readWriteLock.writeLock().lock();  // 讀鎖

2.常用方法:

        lock.lock();// 獲得鎖
        try{
            //處理任務(wù)
        }catch(Exception ex){
        }finally{
            lock.unlock();   // 釋放鎖
        }
        lock.tryLock(); // 嘗試獲得鎖,得到true卵贱,得不到false滥沫,立即返回

悲觀鎖與樂(lè)觀鎖CAS機(jī)制

悲觀鎖

定義:總是假設(shè)最壞的情況侣集,假設(shè)每次取數(shù)據(jù)后都認(rèn)為數(shù)據(jù)會(huì)被其他線程修改,需要保證數(shù)據(jù)的強(qiáng)一致性兰绣。如sychronized關(guān)鍵字和ReentrantLock類世分,都是悲觀鎖。

樂(lè)觀鎖與CAS

定義:假設(shè)每次取得數(shù)據(jù)后缀辩,數(shù)據(jù)不會(huì)被其他線程修改臭埋。
CAS:全稱compareAndSwap,望文生義臀玄,即比較與替換瓢阴。
每次進(jìn)行對(duì)數(shù)據(jù)寫操作時(shí)進(jìn)行一次CAS:
compare:比較工作內(nèi)存中的值A(chǔ)1,是否與主內(nèi)存中地址V中的值A(chǔ)2一致健无;
swap:若A1與A2一致荣恐,則修改地址V中的A2為B;若A1與A2不一致睬涧,則重新讀取地址V中的值,再進(jìn)行任務(wù)處理旗唁,稱為回旋畦浓,該情況可能一直循環(huán)直到一致為止。

CAS下帶來(lái)的ABA問(wèn)題:
按時(shí)間順序有以下任務(wù):
線程1任務(wù):讀地址V检疫,A值修改為B值
線程2任務(wù):讀地址V讶请,A值修改為B值
線程3任務(wù):讀地址V,B值修改為A值
根據(jù)CAS原則屎媳,線程1執(zhí)行后夺溢,線程2回旋,線程3執(zhí)行烛谊,最終值為A
若此時(shí)線程2阻塞风响,則只執(zhí)行1和3,線程2釋放丹禀,根據(jù)CAS原則状勤,執(zhí)行完1和3后,線程2回旋判定A值一致双泪,修改為B持搜,最終值為B
解決方法:每次寫數(shù)據(jù)時(shí),加入版本號(hào)焙矛,判斷A1與A2一致時(shí)葫盼,同時(shí)判斷版本號(hào)是否一致
如concurrent包下的Atomic類,為樂(lè)觀鎖村斟。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贫导,一起剝皮案震驚了整個(gè)濱河市抛猫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌脱盲,老刑警劉巖邑滨,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異钱反,居然都是意外死亡掖看,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門面哥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)哎壳,“玉大人,你說(shuō)我怎么就攤上這事尚卫」殚牛” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵吱涉,是天一觀的道長(zhǎng)刹泄。 經(jīng)常有香客問(wèn)我,道長(zhǎng)怎爵,這世上最難降的妖魔是什么特石? 我笑而不...
    開(kāi)封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮鳖链,結(jié)果婚禮上姆蘸,老公的妹妹穿的比我還像新娘。我一直安慰自己芙委,他們只是感情好逞敷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著灌侣,像睡著了一般推捐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上侧啼,一...
    開(kāi)封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天玖姑,我揣著相機(jī)與錄音,去河邊找鬼慨菱。 笑死焰络,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的符喝。 我是一名探鬼主播闪彼,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了畏腕?” 一聲冷哼從身側(cè)響起缴川,我...
    開(kāi)封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎描馅,沒(méi)想到半個(gè)月后把夸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铭污,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年恋日,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘹狞。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡岂膳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出磅网,到底是詐尸還是另有隱情谈截,我是刑警寧澤,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布涧偷,位于F島的核電站簸喂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏燎潮。R本人自食惡果不足惜喻鳄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望跟啤。 院中可真熱鬧诽表,春花似錦唉锌、人聲如沸隅肥。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)腥放。三九已至,卻和暖如春绿语,著一層夾襖步出監(jiān)牢的瞬間秃症,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工吕粹, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留种柑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓匹耕,卻偏偏與公主長(zhǎng)得像聚请,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容