1、synchronized關鍵字的同步方法
包括兩種用法:synchronized方法和synchronized塊,synchronized控制物件的訪問,每一個對相對應一把鎖,每一個synchronized方法都必須獲得帶哦用該方法物件的鎖才能執行,否則執行緒會阻塞,方法一旦執行,就獨占該鎖,直到該方法回傳才釋放鎖,后面被阻塞的物件才能夠得到這個鎖,繼續執行
缺點:若將一個大的方法申明為synchronized將會影響效率,方法里面需要修改的內容才需要鎖,鎖太多的話會造成資源的浪費
(1)在添加關鍵字以前存在執行緒安全問題:
zhao拿到了第10張票
zhai拿到了第9張票
zhang拿到了第8張票
zhao拿到了第7張票
zhai拿到了第6張票
zhang拿到了第5張票
zhao拿到了第4張票
zhai拿到了第3張票
zhang拿到了第2張票
zhao拿到了第1張票
zhai拿到了第0張票
zhang拿到了第-1張票
(2)添加關鍵字,為方法加鎖:
public class BuyTickets implements Runnable { private int ticketNum=10; boolean flag=true; @Override public void run() { while (flag){ buy(); } } //synchronized實作同步方法 private synchronized void buy(){ if(ticketNum<=0){ flag=false; return; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"拿到了第"+ticketNum--+"張票"); } }
測驗類:
public class Test { public static void main(String[] args) { BuyTickets buyTickets=new BuyTickets(); new Thread(buyTickets,"zhai").start(); new Thread(buyTickets,"zhang").start(); new Thread(buyTickets,"zhao").start(); } }
測驗結果:
zhai拿到了第10張票
zhao拿到了第9張票
zhao拿到了第8張票
zhang拿到了第7張票
zhao拿到了第6張票
zhai拿到了第5張票
zhao拿到了第4張票
zhao拿到了第3張票
zhang拿到了第2張票
zhao拿到了第1張票
沒有出現票為負數的情況,沒有出現票的編號重復的情況
2、synchronized同步塊
可以監視任何物件,但是推薦使用共享資源作為同步監視器,同步方法中無需指定同步監視器,因為同步方法的同步監視器就是this,就是物件本身
第1個執行緒訪問,鎖定同步監視器,執行其中的代碼
第2個執行緒訪問,發現同步監視器被鎖定,無法訪問
第1個執行緒訪問完畢,解鎖同步監視器
第2個執行緒訪問,發現同步監視器沒有鎖,然后鎖定并訪問
(1)對變化的物件加鎖:
public class BankTest extends Thread{ Account account; int drawingMoney;//取出的金額 int nowMoney;//現金 public BankTest(Account account,int drawingMoney,String name){ super(name); this.account=account; this.drawingMoney=drawingMoney; } public void run(){ synchronized (account){ //判斷是否有余額 if(account.money-drawingMoney<0){ System.out.println("余額不足"); return; } try { Thread.sleep(1000);//放大問題的發生性 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("余額:"+account.money); account.money=account.money-drawingMoney;//余額 nowMoney=nowMoney+drawingMoney; System.out.println(this.getName()+"現金:"+nowMoney); } }
public class Account { int money;//余額 String name;//名字 public Account(int money, String name) { this.money = money; this.name = name; } }
public class Test { public static void main(String[] args) { Account account=new Account(1000,"工資"); BankTest bankTest1=new BankTest(account,150,"tom"); BankTest bankTest2=new BankTest(account,200,"jack"); bankTest1.start(); bankTest2.start(); } }
余額:1000 tom現金:150 余額:850 jack現金:200
(2)為集合加鎖:
public class UnSafeList { public static void main(String[] args) { List<String> list=new ArrayList<String>(); for(int i=0;i<10000;i++){ new Thread(()->{ synchronized (list){ list.add(Thread.currentThread().getName()); } }).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
3、JUC
測驗JUC安全型別的集合
public class UnSafeList { public static void main(String[] args) { CopyOnWriteArrayList<String> list=new CopyOnWriteArrayList<String>(); for(int i=0;i<10000;i++){ new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
10000
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/176786.html
標籤:Java
