java多線程的一些筆記 原

java多線程的一些筆記

多線程的目的

  1. 同時幹多件事;
  2. 充分利用CPU資源,特別是多核CPU;
  3. 有些場景下,n個操作需要同時執行

多線程遇到的問題/挑戰

如果n個線程之間沒有資源的共享,則多線程是沒有任何問題的,是線程安全的.
資源共享的場景:
1,讀寫相同的變量,即讀寫相同的內存區;
2,

線程的創建和銷燬會佔用資源,所以大併發情況下,一般採用線程池 參考: http://hw1287789687.iteye.com/blog/2007134

常用解決方案

  1. 使用對象內置鎖;
  2. 使用可重入鎖;
  3. 使用wait ,notifyAll;
  4. 分佈式鎖

鎖的核心作用

保證n個操作 是原子操作,即保證一個CPU時間片只能執行一個原子操作

難點

  1. 確認競態條件是什麼? 是變量?io?
    競態條件,說得通俗一點,就是線程A 需要判斷一個變量的狀態,然後根據這個變量的狀態來執行某個操作。 在執行這個操作之前,這個變量的狀態可能會被其他線程修改。

看一個例子

import java.util.concurrent.atomic.AtomicLong;  
  
public class LazyInitRace {  
    private ExpensiveObject instance=null;  
      
    public ExpensiveObject getInstance(){  
        if(instance==null){  
            instance=new ExpensiveObject();  
        }  
        return instance;  
    }  
}  

在LazyInitRace 中包含了一個競態條件,它可能會破壞這個類的正確性。假定線程A和線程B 同時執行getInstance 方法。A 看到instance 爲空,因此A創建一個新的ExpensiveObject實例。B 同樣需要判斷instance 是否爲空。此時的instance是否爲空,要取決於不可預測的時序,包括線程的調度方式,以及A 需要花多長時間來初始化ExpensiveObject並設置instance。如果當B檢查時,instance爲空,那麼在兩次調用getInstance 時可能會得到不同的對象。

線程A和B的執行時序可能是這樣的:
這裏寫鏈接內容
說明:線程B 在執行紅色部分代碼(判斷instance是否爲空)時,線程A 還沒來得執行完綠色部分的代碼。

  1. 什麼情況下會產生競態條件?

容易混淆的知識點

  1. sleep 和wait 的區別 sleep 會讓出CPU資源,但是不會釋放同步鎖;
    sleep結束,繼續佔用同步鎖, 所以sleep過程中,其他線程依然阻塞;

sleep 和網絡io或文件io導致的阻塞有什麼區別呢?

wait 會讓出同步鎖(s.wait()),同時當前線程會進入 s的等待隊列,
只有調用特定的方法才能喚醒:notify

喚醒之後,並不是馬上獲取鎖,而是阻塞狀態,依然得去競爭鎖

  1. yield 會降低線程的優先級嗎? 不會. yield 只是試圖讓出CPU資源,讓出之後,可能又被OS調度,又獲取到CPU資源

  2. 調用wait 之後,並不是阻塞狀態,而是進入了等待隊列 調用誰的wait 就會進入誰的等待隊列

  3. join 本質上是調用wait wait 對應的喚醒是程序主動操作,而 join對應的喚醒 是jvm 自動操作的.

  4. 調用哪個方法才能創建線程? start()

  5. 線程可以多次啓動嗎? 只能start()一次

  6. volatile 爲什麼不能解決競態條件? volatile 只能保證變量可見性; 說白了,它只能保證某一時刻的狀態是最新的, 只能保證狀態,不能保證過程,
    即它保證不了操作的原子性, 可以拿數據庫的acid 進行類比理解.

  7. 鎖有什麼作用? (1). 同一時間只能有一個線程進入鎖; (2). 保證其中的變量可見性(同volatile 作用)

加深理解

可以類比 數據庫的ACID

參考
https://my.oschina.net/huangweiindex/blog/1919895
https://mp.weixin.qq.com/s/ODJqoiHYwAhRCMnVjunsbQ

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章