今天對synchronized關鍵字的用法又有了更高一層的理解,特此記錄一下。
一直對自己設計的多通道做單不是狠滿意,並發效率低下。因為之前使用的鎖一直是對象鎖(this/類.class),這樣則意味着每個線程搶到CPU執行權之后就會把整個類鎖住,然后執行完被同步的全部代碼后才釋放鎖,后面的線程才能執行同步代碼,導致並發效率低下。還有一個問題就是:假如在某一時刻把整個類都鎖住,那么這時在其他地方調用被鎖住的這個類的其他方法,則要等到釋放鎖后才能調用。
模擬多窗口售票系統:
1 /** 2 * 多線程售票案例: 3 */ 4 public 5 class SellTicket { 6 7 private static final Logger logger = LoggerFactory.getLogger(SellTicket.class); 8 9 public static void main(String[] args) { 10 MyThread unit = new MyThread(); //售票線程單元 11 //六個售票窗口開始同時售票5000張 12 logger.info("開始售票:{}======================="); 13 new Thread(unit,"【窗口一】").start(); 14 new Thread(unit,"【窗口二】").start(); 15 new Thread(unit,"【窗口三】").start(); 16 new Thread(unit,"【窗口四】").start(); 17 new Thread(unit,"【窗口五】").start(); 18 new Thread(unit,"【窗口六】").start(); 19 } 20 } 21 22 /** 23 * 創建線程單元:一個線程單元模擬一個售票窗口進行售票,每執行一次售出票數+1。 24 */ 25 class MyThread implements Runnable{ 26 27 private static Object lock = new Object(); //靜態鎖 28 private int votes = 1; //日預售票數起點 29 30 //售票 31 @Override 32 public void run() { 33 while(true){ 34 //1、用lock靜態所把鎖的粒度縮小,提高並發效率。 35 //2、synchronized (MyThread.class): 把整個類鎖住,這樣很糟糕並且效率低下。比如調用其他方法,也要等得到鎖才能繼續做。 36 synchronized (lock) { //同步鎖:保證在同一時刻最多只有一個線程單元進行售票 37 if (votes > 5000) { 38 //日票數已售完 39 break; 40 } 41 System.out.println(Thread.currentThread().getName()+"成功預訂"+votes+"票"); 42 votes++; 43 } 44 } 45 } 46 }
