synchronized
解释:java语言的一个关键字
作用:实现同步机制,控制多线程的访问,确保同一时刻只有一个线程可以进入临界区执行同步代码。
用法:加在代码块上、加在方法上、加在一个对象,
原理:不管是那种用法,都会有一个对象(指定的对象、class的实例对象、class对象),这个对象又会一一对应一个监视器对象,然后对监视器对象加锁,编译成字节码后,会有monitorenter和monitorexit标记同步代码块的入口和出口
监视器对象(ObjectMonitor)里有一些变量,记录一些信息
ObjectMonitor() { _header = NULL; _count = 0; // 重入次数 _waiters = 0, // 等待线程数 _recursions = 0; _object = NULL; _owner = NULL; // 当前持有锁的线程 _WaitSet = NULL; // 调用了 wait 方法的线程被阻塞 放置在这里 _WaitSetLock = 0 ; _Responsible = NULL ; _succ = NULL ; _cxq = NULL ; FreeNext = NULL ; _EntryList = NULL ; // 等待锁 处于block的线程 有资格成为候选资源的线程 _SpinFreq = 0 ; _SpinClock = 0 ; OwnerIsThread = 0 ; }
wait
解释:是Object类的一个final方法,会抛出InterruptedException
作用:让当前线程进入等待状态,并释放持有的锁
原理:会将当前线程加入ObjectMonitor的_WaitSet,当前线程随即释放锁,并等待在原地,停止执行后续代码
用法:使用synchronized包裹,抛出或者处理中断异常
public void doWait() throws InterruptedException { synchronized (obj) { obj.wait(); } }
notify
解释:是Object类的一个final native方法
作用:随机唤醒一个线程,这个线程是waiting在当前object的monitor,即加入ObjectMonitor的_WaitSet的线程
原理:从ObjectMonitor的_WaitSet中随机取出一个线程唤醒,这个线程随即获取锁,继续执行后续的代码
用法:使用synchronized包裹
public void doNotify() { synchronized (obj) { obj.notify(); } }
notifyAll
同notify,只不过唤醒所有的等待线程,所有的等待线程随即竞争同步锁
下面是一个经典的生产者消费者模型,由于是多个生产者多个消费者,在此,在仓库满了以后,我们使用wait让生产者进入等待,在仓库空了以后让消费者进入等待。当生产者将商品放入仓库以后,通知等待的消费者继续消费 或者 当消费者消费了商品以后,通知等待的生产者继续生产,此处由于是多个生产者和多个消费者,如果使用nofity,可能唤醒的不是想要唤醒的线程。 但是使用notifyAll,需要做一个保护,下面代码中的while。 在仓库满了以后,如果唤醒的生产者竞争到了锁,还是会将商品放入了仓库,导致仓库爆了,或者 在仓库空了以后,如果唤醒的消费者竞争到了锁,会消费不到商品。
public class Test { public static void main(String[] args) { new Test().start(); } private void start(){ Store store = new Store(10); Thread producer1 = new Thread(new Producer("producer1",store, 1000)); Thread producer2 = new Thread(new Producer("producer2",store, 1000)); Thread consumer1 = new Thread(new Consumer("consumer1",store, 1000)); Thread consumer2 = new Thread(new Consumer("consumer2",store, 1000)); Thread consumer3 = new Thread(new Consumer("consumer3",store, 1000)); producer1.start(); producer2.start(); consumer1.start(); consumer2.start(); consumer3.start(); } class Store { final int capacity; final List<String> list; public Store(int capacity){ this.capacity = capacity; list = new ArrayList<>(capacity); } public String take() throws InterruptedException { synchronized (list) { while (list.isEmpty()) { // prevent consumer notify consumer, so use while list.wait(); } String product = list.remove(list.size() - 1); list.notifyAll(); return product; } } public void add(String product) throws InterruptedException { synchronized (list) { while (list.size() >= capacity) { // prevent producer notify producer, so use while list.wait(); } list.add(product); list.notifyAll(); } } } class Producer implements Runnable{ String flag; Store store; int interval; public Producer(String flag, Store store, int interval) { this.flag = flag; this.store = store; this.interval = interval; } @Override public void run() { for(long i=0;;i++) { try { Thread.sleep(interval); } catch (InterruptedException e) { System.out.println("sleep InterruptedException so finish thread "+flag); break; } String product = "product-"+flag+"-"+i; System.out.println(flag+" produce "+product); try { store.add(product); } catch (InterruptedException e) { System.out.println("wait/notify InterruptedException so finish thread "+flag); break; } } } } class Consumer implements Runnable{ String flag; Store store; int interval; public Consumer(String flag, Store store, int interval) { this.flag = flag; this.store = store; this.interval = interval; } @Override public void run() { for(;;) { try { Thread.sleep(interval); } catch (InterruptedException e) { System.out.println("sleep InterruptedException so finish thread "+flag); break; } try { String product = store.take(); System.out.println(flag+" consume "+product); } catch (InterruptedException e) { System.out.println("wait/notify InterruptedException so finish thread "+flag); break; } } } } }
标签:Thread,list,间通信,flag,线程,notify,new,store From: https://www.cnblogs.com/huainanyin/p/18110827