关于Volatile和内存可见性的补充
网上的资料:线程修改一个变量,会把这个变量先从主内存读取到工作内存,然后修改工作内存的值,再写回主内存。
内存可见性:t1频繁读取主内存,效率比较低,就被优化成直接读自己的工作内存。
t2修改了主内存的结果,由于t1没有读主内存,导致修改不能被识别。
工作内存=》cpu寄存器
主内存=〉内存
线程的调度是无序的,但是有些场景,希望线程有序执行
join算是一种但是功能有限
wait:就是让某个线程先暂停等一等
notify:就是让该线程唤醒,继续执行
Wait
wait:发现条件不满足时/时机不成熟,就先阻塞等待。
主要做三件事:
wait必须写到synchronized代码块里面。
1.解锁
2.阻塞等待
3.当收到通知,就唤醒,同时尝试重新获取锁
notify:其他线程构造了一个成熟的条件,就可以唤醒。
wait和notify是Object的方法
notify:进行通知
public static void main(String[] args) throws InterruptedException {
Object object=new Object();
Thread t1=new Thread(()->{
System.out.println("执行前");
synchronized (object){
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("执行后");
});
t1.start();
Thread.sleep(1000);
Thread t2=new Thread(()->{
synchronized (object){
System.out.println("开始");
object.notify();
System.out.println("结束");
}
});
t2.start();
}
必须先执行wait,然后notify,才有效果!
如果现在还没有wait,就notify,相当于一炮打空了!
此时wait无法唤醒,代码不会出其他异常
使用wait,阻塞等待会让线程进入WAITING状态,wait也提供了一个带参数的版本,参数指定是最大等待时间,wait的初心就是进入阻塞的方式。
wait还有有参版本, 当使用有参版本是时,obj.wait(1000)(1秒后还不被唤醒,则强制唤醒)
notifyAll
可以有多个线程,等待同一个对象,比如t1,t2,t3中都调用object.wait,此时main中调用了object.notify(会随机唤醒一个),notifyAll(上述三个唤醒全部),此时这三个线程重新竞争锁然后依次执行。