上述代码在只有两个线程时没有问题。 但多个线程会出错。我试了一下,确实会出错。但是我不能明白为什么就会出错。 不是有synchronized关键字加锁了吗?其实用if判断的话,唤醒后线程会从wait之后的代码开始运行,但是不会重新判断if条件,直接继续运行if代码块之后的代码,而如果使用while的话,也会从wait之后的代码运行,但是唤醒后会重新判断循环条件,如果不成立再执行while代码块之后的代码块,成立的话继续wait。
package com.qcby.lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @author HuangHaiyang * @date 2020/07/02 * @description: description * @version: 1.0.0 */ public class JucTest { public static void main(String[] args) { Goods goods=new Goods(); new Thread(()->{ for (int i = 0; i <10 ; i++) { try { goods.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"一号").start(); new Thread(()->{ for (int i = 0; i <10 ; i++) { try { goods.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"二号").start(); new Thread(()->{ for (int i = 0; i <10 ; i++) { try { goods.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"三号").start(); new Thread(()->{ for (int i = 0; i <10 ; i++) { try { goods.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"四号").start(); } static class Goods{ private int number=0; private Lock lock=new ReentrantLock(); public synchronized void increment() throws InterruptedException { while (number!=0){ this.wait(); } number++; System.out.println(Thread.currentThread().getName()+"=====>"+number); this.notifyAll(); } public synchronized void decrement() throws InterruptedException { while(number==0){ this.wait(); } number--; System.out.println(Thread.currentThread().getName()+"=====>"+number); this.notifyAll(); } } //一号=====>1 //二号=====>0 //一号=====>1 //二号=====>0 //一号=====>1 //二号=====>0 //一号=====>1 //二号=====>0 //一号=====>1 //二号=====>0 //一号=====>1 //二号=====>0 //一号=====>1 //二号=====>0 //一号=====>1 //二号=====>0 //一号=====>1 //二号=====>0 //一号=====>1 //二号=====>0 //三号=====>1 //四号=====>0 //三号=====>1 //四号=====>0 //三号=====>1 //四号=====>0 //三号=====>1 //四号=====>0 //三号=====>1 //四号=====>0 //三号=====>1 //四号=====>0 //三号=====>1 //四号=====>0 //三号=====>1 //四号=====>0 //三号=====>1 //四号=====>0 //三号=====>1 //四号=====>0 // //Process finished with exit code 0 }lock锁实现
package com.qcby.lock; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @author HuangHaiyang * @date 2020/07/02 * @description: description * @version: 1.0.0 */ public class JucTest { public static void main(String[] args) { Goods goods=new Goods(); new Thread(()->{ for (int i = 0; i <10 ; i++) { try { goods.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"一号").start(); new Thread(()->{ for (int i = 0; i <10 ; i++) { try { goods.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"二号").start(); new Thread(()->{ for (int i = 0; i <10 ; i++) { try { goods.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"三号").start(); new Thread(()->{ for (int i = 0; i <10 ; i++) { try { goods.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"四号").start(); } static class Goods{ private int number=0; private Lock lock=new ReentrantLock(); Condition condition = lock.newCondition(); public void increment() throws InterruptedException { lock.lock(); try { while (number!=0){ condition.await(); } number++; System.out.println(Thread.currentThread().getName()+"=====>"+number); condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void decrement() throws InterruptedException { lock.lock(); try { while(number==0){ condition.await(); } number--; System.out.println(Thread.currentThread().getName()+"=====>"+number); condition.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } } }精确通知
package com.qcby.lock; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @author HuangHaiyang * @date 2020/07/02 * @description: description * @version: 1.0.0 */ public class JucTest { public static void main(String[] args) { Data3 data = new Data3(); new Thread(() -> { for (int i = 0; i < 10; i++) { data.printA(); } }, "A").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { data.printB(); } }, "B").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { data.printC(); } }, "C").start(); } } class Data3 { // 资源类 Lock private Lock lock = new ReentrantLock(); private Condition condition1 = lock.newCondition(); private Condition condition2 = lock.newCondition(); private Condition condition3 = lock.newCondition(); private int number = 1; // 1A 2B 3C public void printA() { lock.lock(); try { // 业务,判断-> 执行-> 通知 while (number != 1) { // 等待 condition1.await(); } System.out.println(Thread.currentThread().getName() + "=>AAAAAAA"); // 唤醒,唤醒指定的人,B number = 2; condition2.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void printB() { lock.lock(); try { // 业务,判断-> 执行-> 通知 while (number != 2) { condition2.await(); } System.out.println(Thread.currentThread().getName() + "=>BBBBBBBBB"); // 唤醒,唤醒指定的人,c number = 3; condition3.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void printC() { lock.lock(); try { // 业务,判断-> 执行-> 通知 // 业务,判断-> 执行-> 通知 while (number != 3) { condition3.await(); } System.out.println(Thread.currentThread().getName() + "=>BBBBBBBBB"); // 唤醒,唤醒指定的人,c number = 1; condition1.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }