今天对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 }