1、多執行緒的三大特性
案例描述:
電影院有三個視窗,售兩種票共 100 張,輸**票情況
分析:每次輸出的結果不同,此次結果出現了兩種不安全的情況:相同的票和負數票的情況class
sellticket
implements
runnuble
catch
(interruptexception e)
system.out.
println
(thread.
currrentthread()
.getname()
+"正在出票"
(ticket--)+
"票數");
}}}}
public
class
sellticketdemo
}
那麼那些問題會引起執行緒的不安全?
1>是否是多執行緒環境
2>是否有資料共享
3>是否有多個操作於共享資料
而在以上的**中前兩條是完全符合的,問題在於是否有多個操作共享資料?
注意 ticket-- 操作;cpu並不是簡單的執行了一次減一,而是進行了三步:
1> 從記憶體讀取變數到 cpu
2> 修改變數
3> 寫回記憶體
出現相同的票(cpu的操作原子性決定的)
cpu 的每一次執行都是原子性(最簡單基本)的操作,比如 ticket–其實並不是一次操作;
首先記錄tiket以前的值 50
接著執行 tiket-- 的操作
然後輸出以前的值 50 t1輸出,就在這之間可能 t2 就來了(併發/並行),則 t2 也輸出一樣的了
tiket 的值變成 49
出現負數票的情況,就是在休眠的時候(隨機性和延遲導致)
t1 、t2、t3 恰好都在 100 毫秒內分別進來了,所以三個都會執行
所以最壞情況下:
正在**第 1 張票 ticket = 0
正在**第 0 張票 tiket = -1
正在**第 -1 張票 tiket = -2
常見的非原子性操作:
n++;–n 從記憶體讀取變數到cpu,修改變數、寫回記憶體
物件的new操作 分配物件的記憶體、初始化物件、將物件賦值給變數
2、synchronized 實現執行緒同步
1> 特點:多個執行緒是前提、多個執行緒使用的是同乙個鎖物件synchronized
(物件)
//注意同步可以解決安全問題的根本原因在物件上,該物件如同鎖的功能
//多個執行緒必須是同一把鎖
//鎖的物件是任意物件
2> 好處:解決了多執行緒的安全問題
3> 弊端:當執行緒相對較多時,每個執行緒都會去判斷同步上的鎖,這是很耗費資源的會降低程式的執行效率
修改後執行緒安全
public
class
sell_ticket
implements
runnable
catch
(interruptedexception e)
system.out.
println
(thread.
currentthread()
.getname()
+"正在**"
+(ticket--)+
"票");}
}}}}
public
class
sell_ticketdemo
}
3 執行緒帶來的風險
1 死鎖 產生死鎖的原因 關於死鎖出現的必要條件 這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,這也為我們實際應用中定位死鎖問題,提供了路由。不加鎖,兩線程訪問,變數訪問示例 當兩個執行緒讀寫相同變數時,執行緒a讀取變數然後給予變數賦予乙個新的值,但是寫操作需要兩個儲存器週期。當執...
多執行緒 執行緒安全
原因 當多個執行緒同時共享,同乙個全域性變數或靜態變數。做寫的操作時,可能發生資料衝突問題,也就是執行緒安全問題。但是做讀操作是不會發生資料衝突問題。解決方案 方式一 內建鎖synchronized synchronized保證執行緒原子性,當執行緒進入方法的時候,自動獲取鎖,一旦鎖被其它執行緒獲取...
多執行緒 執行緒安全
public class unsafethread t.start while thread.activecount 1 system.out.println sum 1 從主記憶體中講sum變數複製到執行緒的工作記憶體 2 在工作記憶體中修改變數 1操作 3 將sum變數從執行緒的工作記憶體寫回到...