1、volatile关键字
线程不安全问题的原因,其中有一个就是可见性问题。
此处,就是编译器自己判断有无。把不该优化的逻辑进行优化了。
解决方法:提醒编译器,此处不要优化,====》即volatile关键字。
volatile起到的效果:保证”内存可见性“;但是并不保证原子性。
以JMM角度看vloatile:正常 程序执行过程中,会把主内存数据先加载到工作内存,再进行计算处理;编译器优化可能会导致每次读取的并不是从主内存中读取的,而是直接取工作内存中的缓存。==》可能会导致内存可见性问题。---->此时vloatile起到的效果:保证每次读取数据都是来自于主内存中。
2、wait和notify
多线程执行时最大的问题====》抢占式执行。调度过程时随机的。但有时我们想要多线程按照预期的顺序来执行。
wait,notify就是用来调配线程执行顺序的。
由于wait操作第一步就是释放当前锁,所以前提得是加了锁==》使用synchronized。
保证加锁的对象与调用wait的对象得是同一个对象。
保证调用wait的对象与调用notify的对象,得是同一个对象。
例子:
=》Java中除了有notify,还有notifyAll。
->假设多个线程都在wait,notify是随机唤醒一个。【notify唤醒等待的线程】
->notifyAll则是全部唤醒。即使唤醒了所有wait,这些wait仍需要重新竞争锁,重新竞争的过程仍是串行的。
小结:
(1)wait()让当前线程进入等待状态;notify()唤醒在当前对象上等待的线程。
(2)wait结束等待的条件:1)其他线程调用该线程的notify方法;
2)wait等待时间超时
3)其他线程调用该等待线程的interrupted方法,导致wait抛出异常。
wait和sleep对比:
=》wait需要搭配synchronized使用,但sleep不需要。
=》 wait是Object的方法,sleep是Thread的静态方法。
唯一的相同点就是:都可以让线程放弃执行一段时间。