Java線程及線程安全
什麼是線程
線程是進程的一個最小執行單位
一個程序下最少有一個進程,一個進程下至少有一個線程,或多個線程來增加程序的執行舒服
什麼是守護線程
守護線程是運行在後臺的一種特殊線程,獨立於控制端並且週期性地指定某種任務或等待處理某些發生的事件
在java中垃圾回收線程就是特殊的守護線程
創建線程的方式
1.繼承Thread重寫run方法
2.實現Runnable接口,實現run方法,沒有返回值
3.實現Callable接口,實現call方法,有返回值
線程的狀態
NEW 尚未啓動
RUNNABLE 就緒
RUNNING 運行
BLOCKED 阻塞的(被同步鎖或者IO鎖阻塞)
WAITING 永久等待
TIMED_WAITING 等待指定的時間重新被喚醒的狀態
TERMINATED 執行完成
sleep和wait的區別
sleep:來自Thread,不釋放鎖,時間到會自動恢復
wait:來自object,釋放鎖,可以使用notify、notifyAll直接喚醒
在java程序中怎麼保證多線程的運行安全
- 使用安全類:比如java.util.concurrent下的類
- 使用自動鎖synchronized
- 使用手動鎖Lock
悲觀鎖和樂觀鎖
悲觀鎖:總是假設最壞的情況,每次去拿數據的時候都認爲別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會阻塞直到拿到鎖(共享資源每次只給一個線程使用,其他線程阻塞,用完後再把資源轉讓給其他線程)。
適合用在寫操作比較頻繁的場景
Java中synchronized和ReentrantLock等獨佔鎖就是悲觀鎖思想的實現
樂觀鎖: 總是假設最好的情況,每次去拿數據都認爲別人不會修改,所以不會上鎖,但是更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號機制和CAS算法實現。
適用於多讀的場景,這樣可以提高吞吐量
Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂觀鎖的一種實現方式CAS實現的
Synchronized關鍵字
Java對象頭裏存在一個monitor, 叫監視器鎖
Synchronized裏面有兩個指令:monitorenter monitorexit
monitorenter:每個對象有一個監視器鎖(monitor),當monitor被佔用時就會處於鎖定狀態,線程執行monitorenter指令時嘗試獲取monitor的所有權,過程如下:
- 如果monitor的進入數爲0,則線程進入monitor,然後將進入數設置爲1,該線程即爲monitor的所有者
- 如果線程已經佔用該monitor,只是重新進入,則進入monitor的進入數加1
- 如果其他線程已經佔用了monitor,則該線程進入阻塞狀態,直到monitor的進入數爲0,再重新嘗試獲取monitor的所有權
Monitorexit:執行monitorexit的線程必須是objectref所對應的monitor的所有者,指令執行時,monitor的進入數減1,如果減1後進入數爲0,那線程退出monitor,不再是這個monitor的所有者,其他被這個monitor阻塞的線程可以嘗試去獲取這個monitoer的所有權