文章目錄
- 一、執行緒安全與互斥(案例說明)
- 1.經典案例
- 2.代碼實作
- 小結
- 二、解決思路
- 1.解決辦法——同步代碼塊
- 2.同步代碼塊(SellTicket執行緒)
- 3.解決辦法——同步函式
- 2.同步函式(SellTicket執行緒)
- 總結
一、執行緒安全與互斥(案例說明)
1.經典案例
1、有100張電影票
2、設定三個視窗同時賣電影票
3、觀察賣電影票的程序
2.代碼實作
代碼如下(SellTicket執行緒):
public class SellTicket implements Runnable {
// 定義100張票
private int tickets = 100;
@Override
public void run() {
while (tickets > 0) {
String name = Thread.currentThread().getName();
System.out.println(name + "正在出售第" + tickets + "票");
tickets--;
}
}
}
代碼如下(SellTicket執行緒測驗):
public class Test02 {
public static void main(String[] args) {
SellTicket sellTicket = new SellTicket();
Thread t1 = new Thread(sellTicket,"視窗1");
Thread t2 = new Thread(sellTicket,"視窗2");
Thread t3 = new Thread(sellTicket,"視窗3");
t1.start();
t2.start();
t3.start();
}
}
輸出:

小結
觀察SellTicket執行緒測驗輸出我圈出來的那部分出現了錯誤錯誤賣票,由于輸出版面有限,其實還有一個錯誤就是可能會賣出負的票數
多個執行緒同時訪問共享資源很可能出現執行緒安全問題
二、解決思路
對多操作共享的陳述句為了保證各執行緒都執行完成,在某執行緒執行程序中,其他執行緒不可以參與執行
1.解決辦法——同步代碼塊
同步代碼塊中的鎖物件可以是任意物件,在進入代碼塊時需要獲得鎖物件,如果得到鎖物件則等待;在退出代碼塊時自動釋放鎖物件,
任何時刻只能有一個執行緒可以獲得對同步監視器的鎖定,當同步代碼塊執行結束后,該執行緒自然會釋放對同步監視器物件的鎖定,
在java程式運行中可以同任何物件作為同步監視器物件,只要保證共享資源的這幾個執行緒鎖的是同一同步監視物件即可,
語法:
synchronized (this) {
需要被同步的代碼
}
2.同步代碼塊(SellTicket執行緒)
代碼如下(同步代碼塊(SellTicket執行緒)):
public class SellTicket implements Runnable {
// 定義100張票
private int tickets = 100;
@Override
public void run() {
// 同步代碼塊(加鎖)
synchronized (this) {
while (tickets > 0) {
String name = Thread.currentThread().getName();
System.out.println(name + "正在出售第" + tickets + "票");
tickets--;
}
}
}
}
代碼如下(同步代碼塊(SellTicket執行緒)測驗):
public class Test02 {
public static void main(String[] args) {
SellTicket sellTicket = new SellTicket();
Thread t1 = new Thread(sellTicket,"視窗1");
Thread t2 = new Thread(sellTicket,"視窗2");
Thread t3 = new Thread(sellTicket,"視窗3");
t1.start();
t2.start();
t3.start();
}
}
代碼如下(同步代碼塊(SellTicket執行緒)測驗輸出):
視窗1正在出售第100票
視窗1正在出售第99票
視窗1正在出售第98票
視窗1正在出售第97票
視窗1正在出售第96票
視窗1正在出售第95票
視窗1正在出售第94票
視窗1正在出售第93票
視窗1正在出售第92票
視窗1正在出售第91票
視窗1正在出售第90票
視窗1正在出售第89票
視窗1正在出售第88票
視窗1正在出售第87票
視窗1正在出售第86票
視窗1正在出售第85票
視窗1正在出售第84票
視窗1正在出售第83票
視窗1正在出售第82票
視窗1正在出售第81票
視窗1正在出售第80票
視窗1正在出售第79票
視窗1正在出售第78票
視窗1正在出售第77票
視窗1正在出售第76票
視窗1正在出售第75票
視窗1正在出售第74票
視窗1正在出售第73票
視窗1正在出售第72票
視窗1正在出售第71票
視窗1正在出售第70票
視窗1正在出售第69票
視窗1正在出售第68票
視窗1正在出售第67票
視窗1正在出售第66票
視窗1正在出售第65票
視窗1正在出售第64票
視窗1正在出售第63票
視窗1正在出售第62票
視窗1正在出售第61票
視窗1正在出售第60票
視窗1正在出售第59票
視窗1正在出售第58票
視窗1正在出售第57票
視窗1正在出售第56票
視窗1正在出售第55票
視窗1正在出售第54票
視窗1正在出售第53票
視窗1正在出售第52票
視窗1正在出售第51票
視窗1正在出售第50票
視窗1正在出售第49票
視窗1正在出售第48票
視窗1正在出售第47票
視窗1正在出售第46票
視窗1正在出售第45票
視窗1正在出售第44票
視窗1正在出售第43票
視窗1正在出售第42票
視窗1正在出售第41票
視窗1正在出售第40票
視窗1正在出售第39票
視窗1正在出售第38票
視窗1正在出售第37票
視窗1正在出售第36票
視窗1正在出售第35票
視窗1正在出售第34票
視窗1正在出售第33票
視窗1正在出售第32票
視窗1正在出售第31票
視窗1正在出售第30票
視窗1正在出售第29票
視窗1正在出售第28票
視窗1正在出售第27票
視窗1正在出售第26票
視窗1正在出售第25票
視窗1正在出售第24票
視窗1正在出售第23票
視窗1正在出售第22票
視窗1正在出售第21票
視窗1正在出售第20票
視窗1正在出售第19票
視窗1正在出售第18票
視窗1正在出售第17票
視窗1正在出售第16票
視窗1正在出售第15票
視窗1正在出售第14票
視窗1正在出售第13票
視窗1正在出售第12票
視窗1正在出售第11票
視窗1正在出售第10票
視窗1正在出售第9票
視窗1正在出售第8票
視窗1正在出售第7票
視窗1正在出售第6票
視窗1正在出售第5票
視窗1正在出售第4票
視窗1正在出售第3票
視窗1正在出售第2票
視窗1正在出售第1票
3.解決辦法——同步函式
對于同步方法(函式)來說,無需顯示指定同步監視器,靜態方法的同步監視器物件是當前類的class物件,非靜態方法的同步監視器物件呼叫當前方法的this物件
語法:
synchronized 函式回傳值 函式名([引數串列]) {
需要被同步的代碼塊
}
2.同步函式(SellTicket執行緒)
代碼如下(同步函式(SellTicket執行緒)):
public class SellTicket implements Runnable {
// 定義100張票
private int tickets = 2000;
@Override
public void run() {
while (true) {
sellTicket();
}
}
// 同步函式(加鎖)
public synchronized void sellTicket() {
if(tickets>0) {
String name = Thread.currentThread().getName();
System.out.println(name + "正在出售第" + tickets + "票");
tickets--;
}
}
}
代碼如下(同步函式(SellTicket執行緒)測驗):
public class Test02 {
public static void main(String[] args) {
SellTicket sellTicket = new SellTicket();
Thread t1 = new Thread(sellTicket,"視窗1");
Thread t2 = new Thread(sellTicket,"視窗2");
Thread t3 = new Thread(sellTicket,"視窗3");
t1.start();
t2.start();
t3.start();
}
}
代碼如下(同步函式(SellTicket執行緒)測驗輸出):
視窗1正在出售第100票
視窗3正在出售第99票
視窗3正在出售第98票
視窗3正在出售第97票
視窗3正在出售第96票
視窗3正在出售第95票
視窗3正在出售第94票
視窗3正在出售第93票
視窗3正在出售第92票
視窗3正在出售第91票
視窗3正在出售第90票
視窗3正在出售第89票
視窗3正在出售第88票
視窗3正在出售第87票
視窗3正在出售第86票
視窗3正在出售第85票
視窗3正在出售第84票
視窗3正在出售第83票
視窗3正在出售第82票
視窗3正在出售第81票
視窗3正在出售第80票
視窗3正在出售第79票
視窗3正在出售第78票
視窗3正在出售第77票
視窗3正在出售第76票
視窗3正在出售第75票
視窗3正在出售第74票
視窗3正在出售第73票
視窗3正在出售第72票
視窗3正在出售第71票
視窗3正在出售第70票
視窗3正在出售第69票
視窗3正在出售第68票
視窗3正在出售第67票
視窗3正在出售第66票
視窗3正在出售第65票
視窗3正在出售第64票
視窗3正在出售第63票
視窗3正在出售第62票
視窗3正在出售第61票
視窗3正在出售第60票
視窗3正在出售第59票
視窗3正在出售第58票
視窗3正在出售第57票
視窗3正在出售第56票
視窗3正在出售第55票
視窗3正在出售第54票
視窗3正在出售第53票
視窗3正在出售第52票
視窗3正在出售第51票
視窗3正在出售第50票
視窗3正在出售第49票
視窗3正在出售第48票
視窗3正在出售第47票
視窗3正在出售第46票
視窗3正在出售第45票
視窗3正在出售第44票
視窗3正在出售第43票
視窗3正在出售第42票
視窗3正在出售第41票
視窗3正在出售第40票
視窗3正在出售第39票
視窗3正在出售第38票
視窗3正在出售第37票
視窗3正在出售第36票
視窗3正在出售第35票
視窗3正在出售第34票
視窗3正在出售第33票
視窗3正在出售第32票
視窗3正在出售第31票
視窗3正在出售第30票
視窗3正在出售第29票
視窗3正在出售第28票
視窗3正在出售第27票
視窗3正在出售第26票
視窗3正在出售第25票
視窗3正在出售第24票
視窗3正在出售第23票
視窗3正在出售第22票
視窗3正在出售第21票
視窗3正在出售第20票
視窗3正在出售第19票
視窗3正在出售第18票
視窗3正在出售第17票
視窗3正在出售第16票
視窗3正在出售第15票
視窗3正在出售第14票
視窗3正在出售第13票
視窗3正在出售第12票
視窗3正在出售第11票
視窗3正在出售第10票
視窗3正在出售第9票
視窗3正在出售第8票
視窗3正在出售第7票
視窗3正在出售第6票
視窗3正在出售第5票
視窗3正在出售第4票
視窗3正在出售第3票
視窗3正在出售第2票
視窗3正在出售第1票
總結
1、同步提升了安全性,但是降低了效率
2、任意的一個物件都可以作為鎖物件
3、多個執行緒操作共享資料的鎖必須是同一個鎖,否則加鎖無效
4、只有真正存在執行緒安全問題的時候才使用同步代碼塊或者同步函式,否則會降低效率
5、多執行緒程式執行具有隨機性,誰搶到就誰執行,測驗輸出就可以觀察出來
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/264145.html
標籤:java
上一篇:Java例外處理的十條建議
