JAVA 多線程同步與互斥


1. 為什么需要互斥:

​互斥操作  保證了  多線程操作的  原子性 ,

java的 互斥 語義 有 synchronized 關鍵字 提供.   

主要方式 有  同步代碼塊 和  同步方法 兩種

2. 整數自增操作

常見的線程安全問題:

  • 從內存中 讀數據  到寄存器,<---進入一個線程

  • 從寄存器 +1 

  • 寫會內存

像這種不是一條指令就能完成的操作 ,並且 有多個線程操作統一資源的時候 ,要保證 上面 三步操作一次執行完,而不被其他線程干擾(原子性:要么  都不執行 ,要么 全部執行)

3. 線程的等待

Thread.join() ;: 

java 中的 主線程  默認會 等待 其他線程的  結束

start() 的 作用是 啟動 一個線程,  使得 調用處 的線程  流程 一分為二

而join() 方法 則 相反 ,.使得 兩個執行流程 合二為一

4. 同步

同步就是  要保證 兩個線程事件 執行的 時序關系

支持“同步”操作的調用叫做“同步原語”,包括:互斥、條件變量、信號量、信箱、事件標志和Spinlock等

  1. wait() 等待通知,該調用會阻塞當前線程。

  2. notify() 發出通知,如果有多個線程阻塞在該obj上,該調用會喚醒一個(阻塞)等待該obj的線程。

  3. notifyAll()發出通知,如果有多個線程阻塞在該obj上,該調用會喚醒所有(阻塞)等待該obj的線程。

5. 信號丟失

wait/notify/notifyAll提供了一種線程間事件通知的方式,但這種通知並不能被有效的“記住”;所以,就存在通知丟失(notify missing)的可能——發出通知的線程先notify,接收通知的線程后wait,此時這個事先發出的通知就會丟失。在POSIX規范上,叫做信號丟失;由於現在的多數操作系統(LINUX,Mac,Unix)都遵循POSIX;所以“信號丟失”這個詞使用的更廣泛。

6. 虛假喚醒

虛假喚醒(spurious wakeup)在采用條件等待時,我們使用的是

while(條件不滿足){
   condition_wait(cond, mutex);
}
而不是:
If( 條件不滿足 ){
   Condition_wait(cond,mutex);
}

這是因為可能會存在虛假喚醒”spurious wakeup”的情況。
也就是說,即使沒有線程調用condition_signal, 原先調用condition_wait的函數也可能會返回。此時線程被喚醒了,但是條件並不滿足,這個時候如果不對條件進行檢查而往下執行,就可能會導致后續的處理出現錯誤。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM