juc是java.util.current的简写,意思是并发编程。
锁是什么?如何判断锁的是谁?
生产者和消费者问题
synchronized版本
package com.demo.juc.pc;
/**
* 线程之间的通信问题,生产者和消费者问题!
* 线程交替执行
*
* a b 两个线程操作同一个变量 num
* a num++
* b num--
*
* 这两条线程是互相隔离的,它们彼此不知道对方是++还是--
* 需要一种机制使它们之间产生通信,
* 比如a++后告诉b该--了,b--后再告诉a该++了
*
* 解决:
* 等待唤醒,通知唤醒
*
*/
public class A {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 5; i++) {
data.increment();
}
},"a").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
data.decrement();
}
},"b").start();
// a-->1
//b-->0
//a-->1
//b-->0
//a-->1
//b-->0
//a-->1
//b-->0
//a-->1
//b-->0
}
}
class Data{ // 数字,资源类
private int number = 0;
// ++
public synchronized void increment(){
if (number!=0){
// 等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number++;
// 通知其他线程,++完毕,开始--
System.out.println(Thread.currentThread().getName()+"-->"+number);
this.notifyAll();
}
// --
public synchronized void decrement(){
if (number==0){
// 等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number--;
System.out.println(Thread.currentThread().getName()+"-->"+number);
this.notifyAll();
}
}
虚假唤醒
多线程环境下,有多个线程执行了wait()方法,需要其他线程执行notify()或者notifyAll()方法去唤醒它们,假如多个线程都被唤醒了,但是只有其中一部分是有用的唤醒操作,其余的唤醒都是无用功;对于不应该被唤醒的线程而言,便是虚假唤醒。
以上代码是两个线程,但是如果四个线程的话,线程就不安全了。
解决虚假唤醒的问题,只需将上面的if判断改为while即可。
为什么 if会出现虚假唤醒?
- 因为if只会执行一次,执行完会接着向下执行if(){}后边的逻辑;
- 而while不会,直到条件满足才会向下执行while(){}后边的逻辑。
如何避免虚假唤醒
使用while循环去循环判断一个条件,而不是使用if只判断一次条件;即wait()要在while循环中。
部分内容转载自:
https://blog.csdn.net/Saintmm/article/details/121092830
https://www.bilibili.com/video/BV1B7411L7tE/?p=8&spm_id_from=pageDriver&vd_source=64c73c596c59837e620fed47fa27ada7
无论你在背后喊刘怡婷或房思琪,我都会回头的。
房思琪的初恋乐园
林奕含