首先对上一章节的指令重排序,在进行解释一下;
假设现在有连个线程 t1 和 t2
t1频繁(速度特别快)读取主内存,效率比较低,就被优化成直接读自己的工作内存。
t2修改了主内存的结果,由于t1没有读主内存,导致修改不能被识别到。
1.什么是主内存,什么是工作内存
工作内存和主内存都是由英文work memory和main memory翻译来的。所以,工作内存不一定非要是内存,可以是记忆,存储区,不一定是特指“内存条”。
我们平常也会有这样的一组概念 CPU寄存器和内存,那么这两组概念有什么区别?
其实在很久以前的CPU,上面只有寄存器那个时候我们就可以理解为工作内存就是寄存器,主内存就是内存条,随着时代的进步,现在的CPU上不仅有寄存器,还有了缓存,而且CPU不仅仅有一个缓存,一般都是三级缓存.如下图所示:
随着缓存的出现,我们就不能说都是在CPU寄存器上读取的数据,此时JVM就引入了一组新的概念,工作内存和主内存.
工作内存准确来说,代表cpu寄存器+缓存(CPU内部存储数据的空间).
2.读取的速度:
1.cpu读寄存器速度比读内存快3-4个数量级.
2.缓存读取速度介于寄存器和内存之间。
L1最快,空间最小(仍然比寄存器慢)
L3最慢,空间最大(仍然比内存快很多)
3.CPU读取数据的顺序
1.先看寄存器里有没有
2.没有,看L1有没有
3.没有,看L2有没有
4.没有,看L3有没有
5.没有,看内存有没有
具体缓存的大小,对于程序效率的影响,也看实际的应用场景。
下面回归今天的主题👇👇👇👇
目录
1.wait 和notify
2. wait 和 sleep 的对比(面试题)
1.wait 和notify
线程的调度是无序的,随机的。但是,也是有一定的需求场景的,希望线程有序执行。
join是一种控制顺序的方式,但是功效有限。
wait就是让某个线程先暂停下来,等一等。
wait主要做三件事:
1.解锁
2.阻塞等待
3.当收到通知的时候,就唤醒,同时尝试重新获取锁。
注意:
notify就是把该线程唤醒,能够继续执行。
wait和notify是Object的方法
只要你是个类对象(不是内置类型/基本数据类型),都是可以使用wait和notify。
代码讲解:
public class ThreadDemo13 {
public static void main(String[] args) throws InterruptedException {
Object locker = new Object();
Thread t1 = new Thread(()->{
synchronized(locker){
try {
System.out.println("wait 开始");
locker.wait();
System.out.println("wait 结束");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("2");
});
Thread.sleep(1000);
Thread t2 = new Thread(()->{
synchronized (locker){
System.out.println("notify 开始");
locker.notify();
System.out.println("notify 结束");
}
System.out.println("1");
});
t1.start();
t2.start();
}
}
上述代码就是在t1线程里面加了一个wait,在t2线程中加了notify用来唤醒t1线程的wait.
1.使用wait,阻塞等待会让线程进入WAITING状态。wait也提供了一个带参数的版本,参数指定的是最大等待时间。不带参数的wait是死等,带参数的wait就会等最大时间之后,还没有人通知,就自己唤醒自己。
2.唤醒操作,还有一个notifyAll。可以有多个线程堵塞,等待同一个对象唤醒。
3.如果在t1,t2,t3中都调用object.wait。此时在main中调用了object.notify 会随机唤醒上述的一个线程。(另外两个仍然会是waiting状态)
4.wait 结束等待的条件:
1.其他线程调用该对象的 notify 方法.
2.wait 等待时间超时 (wait 方法提供一个带有 timeout 参数的版本, 来指定等待时间).
3.其他线程调用该等待线程的 interrupted 方法, 导致 wait 抛出 InterruptedException 异常.
总结:
1.wait需要搭配synchronized使用,sleep不需要。
2.wait是Object的方法,sleep是Thread的静态方法。
wait和sleep都是可以提前唤醒的。
他们最大的区别在于初心不同。
wait解决的是线程之间的顺序控制
sleep单纯是让当前线程休眠一会。
2. wait 和 sleep 的对比(面试题)
其实理论上 wait 和 sleep 完全是没有可比性的,因为一个是用于线程之间的通信的,一个是让线程阻塞一段时间,唯一的相同点就是都可以让线程放弃执行一段时间.
当然为了面试的目的,我们还是总结下:
1. wait 需要搭配 synchronized 使用. sleep 不需要.
2. wait 是 Object 的方法 sleep 是 Thread 的静态方法.