日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java线程同步——条件对象+synchronized 关键字

發布時間:2023/12/3 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java线程同步——条件对象+synchronized 关键字 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【0】README

0.1) 本文描述轉自 core java volume 1, 源代碼為原創,旨在理解 java線程同步——條件對象+synchronized 關鍵字 的相關知識;
0.2)for full source code : https://github.com/pacosonTang/core-java-volume/blob/master/chapter14/SynchBank.java


【1】條件對象

1.1)為什么引入條件對象:通常,線程進入臨界區, 卻發現在某一條件滿足后它才能執行, 要使用一個條件對象來管理那些已經獲得了一個鎖但是卻不能做有用工作的線程;
1.2)看個荔枝:

  • 1.2.1)我們避免選擇沒有足夠資金的賬戶作為轉出賬戶:
if(bank.getBalance(from) >= amount)bank.transfer(from, to, amount)
  • 1.2.2)當前線程有可能在 調用 transfer之前就被CPU切斷了
if(bank.getBalance(from) >= amount) // thread might be deactived at this pointbank.transfer(from, to, amount)
  • 1.2.3)我們必須要確保: 沒有其他線程在本檢查余額 與轉賬活動間修改余額。通過使用鎖保護來支持這一點:

1.3)一個鎖對象可以有一個或多個條件對象。 你可以使用 newCondition 方法獲得一個條件對象;

  • 1.3.1)如果transfer 發現余額不足,它可以調用:
suffcientFunds.await(); 使得當前線程阻塞了,并放棄鎖;(干貨——為了避免死鎖+await方法的作用)

1.4)等待獲得鎖的線程和調用 await 方法的線程存在本質的不同:

  • 1.4.1)一旦一個線程調用 await 方法, 它進入該條件的等待集, 當鎖可用時,該線程不能馬上解除阻塞;
  • 1.4.2)相反,它處于阻塞狀態, 直到另一個線程調用同一個條件上的signalAll 方法為止, 這一調用重新激活 因為這一條件而等待的所有線程;
  • 1.4.3)一旦鎖成為可用的, 它們中的某個將從 await 方法調用返回, 獲得該鎖并從阻塞的地方繼續執行;

1.5)容易造成死鎖:(干貨)

  • 1.5.1)原因: 當一個線程調用 await 方法時, 它沒有辦法重新激活自身。 它寄希望于其他線程,然而,如果最后一個活動線程在解除其他線程的阻塞狀態之前就調用了 await 方法, 那么它就 被阻塞了, 這將導致所有的線程都處于阻塞狀態,導致死鎖;
  • 1.5.2)解決方法:應該何時調用 signalAll 方法呢?經驗上講, 在對象的狀態有利于等待線程的方法改變時調用 signalAll方法;

Attention)

  • A1)注意, 調用 signalAll 不會立即激活一個等待線程, 它僅僅解除等待線程的阻塞,以便這些線程可以在當前線程退出同步方法后, 通過競爭實現對對象的訪問;(干貨——signalAll方法的作用)
  • A2)另一個方法 signal: 則是隨機解除等待集中某個線程的阻塞狀態,這比解除所有線程的阻塞更加有效, 但也存在危險;(干貨——signal 方法的作用)

Warning)

  • W1)當一個線程擁有某個條件的鎖時,它僅僅可以在該條件上調用 await, signalAll 或 signal 方法;
  • W2)即是, 一個系統中有多個條件變量(Condition), 每個條件上等待的線程不同, 某條件下的線程只喚醒該條件下的等待進程;

【2】synchronized 關鍵字

2.1)總結一下有關鎖和條件的關鍵之處:

  • 2.1.1)鎖用來保護代碼片段, 任何時刻只能有一個線程執行被保護的代碼;
  • 2.1.2)鎖可以管理試圖進入被保護代碼段的線程;
  • 2.1.3)鎖可以擁有一個或多個相關的條件對象;
  • 2.1.4)每個條件對象管理那些已經進入被保護的代碼段但還不能運行的線程;

2.2) Lock 和 Condition 接口專門為 程序設計人員提供了 高度的鎖定控制;
2.3)synchronized 關鍵字: 可用于定義 同步方法和 同步塊以保護這個方法或同步塊中的代碼 在同一時間只能被一個線程訪問;
2.4)wait 方法添加一個線程到等待集中, notifyAll/notify 方法解除等待線程的阻塞狀態;

  • 2.4.1)換句話說: 調用wait 和 notifyAll 方法 等價于 condition.await() 和 condition.signalAll() 方法;

Annotation)

  • A1) wait, notifyAll , notify 方法是 Object的final方法;
  • A2) await, signalAll, signal 方法 是Condition 接口的方法, 以便與上述方法不會發生沖突;

2.5) 內部鎖和條件存在一些局限:

  • 2.5.1)不能中斷一個正在試圖獲得鎖的過程;
  • 2.5.2)試圖獲得鎖時不能設定超時;
  • 2.5.3)每個鎖僅有單一條件,可能是不夠的;

2.6)在代碼中應該使用哪一種? Lock 和 Condition 對象還是同步方法?下面是建議:

  • 2.6.1)最好既不用 Lock/Condition 也不用 synchronized關鍵字; 在許多case 下,你可以使用 java.util.concurrent 包中的一種機制, 它會為你處理所有的加鎖。 你會看到如何使用阻塞隊列來不同完成一個共同任務的線程; (干貨——阻塞隊列的作用)
  • 2.6.2)如果 synchronized關鍵字適合, 請盡量使用它;
  • 2.6.3)如果特別需要 Lock/Condition 結構提供的獨有特性, 才使用 Lock/Condition;

總結

以上是生活随笔為你收集整理的java线程同步——条件对象+synchronized 关键字的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。