二刷多線程核心篇筆記

進程是程序向操作系統申請資源的基本單位。線程是進程中可獨立執行的最小單位。

線程中調用start之前設置Daemon爲true即爲守護線程,否則爲用戶線程。

守護線程不會影響java虛擬機正常停止。用戶線程會阻止java虛擬機正常停止,即全部用戶線程結束之後java虛擬機纔會結束。所以守護線程一般執行重要性不高的任務,比如監視情況

Thread 方法
currenThread – 返回當前執行線程
run – 由java虛擬機直接調用,而不是程序
start-- 開啓一個線程,同一個線程的start不能被多次調用
join–等待線程,A線程調用B線程的join,那麼A線程等待B線程結束後才執行
static yield – 主動放棄佔用cpu
static sleep-- 睡眠一段時間後執行

子線程和父線程生命週期沒有必然聯繫,父線程結束,子線程還能跑。相反也一樣

線程狀態
new 新建–已創建而未被調用start方法。只有一次處於這個狀態(start只能被調用一次)
runnable 運行–是一個複合狀態有:ready和running。前者表示線程已經準備可以被調度,後者表示線程正在運行。ready也叫作活躍線程
blocked :線程發起阻塞式io,或者申請一個其他線程持有的獨佔資源(比如鎖)
waiting 等待:線程執行了某些操作就會處於等待其他線程執行完特定操作例如 wait,join
timed_waiting :和wait類似,不過並非等待其他線程,而是等待一個時間後自動變爲runnable
terminated :線程執行完畢。只有一次處於這個狀態(start只能被調用一次)

多線程優點:
提高系統吞吐量:例如一個線程因爲io操作處於等待,其他線程可以執行其他
提高響應性:比如一個線程負責加載數據,一個線程負責打開界面。這樣就不會導致軟件界面被凍住情況
充分利用多核處理資源:
最小化對系統資源使用:多個線程可以共享所在進程所申請的資源(例如內存空間)
簡化程序結構:

多線程問題:
線程安全:多個共享數據,產生數據不一致,丟失更新,髒讀數據
線程活性:runnable是最好的狀態。但有可能產生死鎖問題。還有線程飢餓問題:某些線程永遠得不到處理器執行機會。
上下文切換:處理器執行一個線程向執行另一個線程動作叫上下文切換。增加系統消耗
可靠性:某個進程突然中止例如內存泄漏導致java虛擬機奔潰,那麼所在該進程的線程都會中止。

多線程編程就是把任務處理方式從串行改成併發(一段時間內交替方式完成多個任務)

竟態:計算的正確性依賴於相對時間順序(有序性)或者線程交錯(可見性)

竟態產生條件:read-modify-write(讀-改-寫) check-then-act(檢測而後行動) 共享變量(局部變量不會)

arrayList HashMap SimpleDateFormat 都是非線程安全

原子操作:1.不可分割。執行線程以外任意線程看來是不可分割。所謂不可分割,指訪問共享變量的操作要麼執行結束,要麼尚未執行。
2.或者當兩個原子操作O1,O2共同訪問一個共享變量時,O1執行期間(開始執行未執行結束),其他線程無法執行O2操作。這樣排除了一個線程執行一個操作期間另一個線程讀取或者修改該訪問的共享變量導致髒讀和丟失更新
3.原子操作+原子操作!=原子操作

原子操作針對共享變量而言,局部變量無所謂或者乾脆看成原子操作。並且是在多線程下才有該概念。

實現原子性:使用鎖(具有排他性,軟件層面),使用CAS指令(硬件層面)

long和double以外任何類型變量的寫操作都是原子操作。
原因:java對long/double會佔用64位,而32位虛擬機對這種變量寫操作分爲兩個步驟,比如先寫低32,再寫高32.

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