上下文切換
當一個進程中的一個線程由於其時間片用完或者其自身原因被迫或者主動暫停其運行時,另外一個線程可以被操作系統選中占用處理器開始或者繼續其運行。這種一個線程被暫停,即被剝奪處理器使用權,另一個線程選中開始或者繼續運行的過程就叫:線程上下文切換。
切出: 一個線程被剝奪處理器的使用權而被暫停運行就被稱為切出。
切入: 一個線程被操作系統選中或者開始繼續其運行就被稱為切入。
上下文
切入切出的時候操作系統需要保存和恢復相應的進度信息,即切入切出那一刻相應的線程所執行的任務進行到什么程度。這個進度信息就被稱為上下文。
他一般包括通用寄存器的內容和程序計數器的內容。在切出時,操作系統將上下文保存到內存,以便被切出的線程稍后占用處理器繼續其運行時能夠在此基礎上進展。在切入時,操作系統需要就從內存中加載(恢復)被選中線程的上下文,以在之前的基礎上繼續進展。
上下切換的分類:
- 自發性上下文切換:由於其自身因素導致的切出如:
- Thread.sleep()
- Object.wait()
- Thread.join()
- LockSupport.park()
- 線程的I/O操作
- 等待其他線程持有的鎖
- 非自發性上下文切換:由於線程調度器的原因被迫切。
- 時間片用完
- 其他優先級更高的線程需要運行
上下文切換的開銷:
- 直接開銷
- 操作系統保存和恢復上下文所需的開銷,主要是時間開銷
- 線程調度器進行線程調度的開銷(如按照規則決定哪個線程會占用處理器運行)
- 間接開銷
- 處理器高速緩存重新加載的開銷
上下文切換存在開銷,所以也並不是線程的數量越多越好,它可能導致的上下文開銷也越大。所以多線程設計減少上下文切換也是一個重要的考量因素。
線程的活性故障
線程有與資源的稀缺性或者自身的問題和缺陷導致一直處於非RUNNABLE狀態,或者線程處於RUNNABLE狀態但是其執行的任務卻一直無法進展的現象就稱為線程活性故障
線程活性故障的幾種情況:
- 死鎖:線程互相處於等待狀態
- 鎖死
- 活鎖:線程處於RUNNBALE狀態,但是任務卻絲毫沒有進展。
- 飢餓:線程因其無法獲得其所需的資源而使得任務無法執行無法進展的現象。
資源爭用與調度
排他性資源: 一次只能被一個線程占用的資源被稱為:排他性資源
資源爭用: 在一個資源占有一個排他性資源進行訪問(讀寫)而未釋放其對資源的所有權,其他線程視圖訪問該資源的情況稱為:資源爭用。
高並發: 同一時間內處於運行狀態的線程數量越多,我們就稱並發的程度越高。(相對)
多線程的理想狀態是高並發、低爭用
資源調度
資源調度 :在多線程申請同一個排他性資源的情況下,決定哪個線程會被授予該資源的獨占權,即哪個申請者占有該資源的過程就叫:資源的調度。
資源的持有線程 : 獲得資源獨占權而又未釋放資源獨占權的線程。
公平性 : 資源的申請線程是否按照其申請順序而被授予資源的獨占權。