【多线程】-- 多线程3
文章目录6.volatile 关键字6.1 volatile能保证内存可见性6.1.1 CPU层面6.1.2 Java层面6.2 volatile保证有序性6.3 volatile不保证原子性7. wait 和 notify7.1 wait()方法和notify()方法7.3 notifyAll()方法7.4 wait() 和 sleep() 的对比面试题6.volatile 关键字publicclassDemo_601{staticintflg0;publicstaticvoidmain(String[]args){Threadt1newThread(()-{System.out.println(Thread.currentThread().getName()线程启动);while(flg0){//不停的循环。处理任务。}System.out.println(Thread.currentThread().getName()线程退出);},t1);t1.start();Threadt2newThread(()-{System.out.println(Thread.currentThread().getName()线程启动);ScannerscannernewScanner(System.in);System.out.println(请输入一个非零的整数);flgscanner.nextInt();System.out.println(Thread.currentThread().getName()线程退出);},t2);t2.start();}}输出结果t2线程正常结束并且已经修改了flg变量的值但是t1没有结束整个进程也没有结束结果不及预期线程安全问题产生。问题产生的原因对于线程t1来说只是比较flg这个变量的值从来都没有修改过所以CPU认为这个值永远也不会改变从而也不会重新从内存中读取值。为了提高运行效率这个值一般存在寄存器或CPU的缓存中。在Java层面我们叫这块内存是寄存器在JVM层面我们叫这块内存是工作内存。在多线程的环境下就会出现我们看到的这个问题一个线程修改了另一个线程无法感知到的变量。6.1 volatile能保证内存可见性6.1.1 CPU层面MESI缓存一致性协议可以理解为一种通知机制。当所有的处理器没有修改共享变量时各自的处理器只读取自已缓存中的值从而提升效率。当某一个处理器往主内存中写回数据的时候让缓存中的值失效通知其他处理器从主内存中重新获取新的值。6.1.2 Java层面内存屏障作用是保证指令执行的先后顺序从而保证内存可见性。为变量加上volatile关键字进行修饰之后的输出结果6.2 volatile保证有序性用volatile修饰过的变量由于前后有内存屏障保证了指令的执行顺序也可以理解为告诉编译器不要进行指令重排。6.3 volatile不保证原子性volatile 和 synchronized 有着本质的区别.synchronized能够保证原⼦性,volatile保证的是内存可⻅性.7. wait 和 notifywait 和 notify 是Object类中的方法每个对象都可以调用这个方法作用安排线程的执行顺序。join 和 wait 是两种不同的操作join是Thread类中的方法wait 和 notify 是Object 类中的方法。7.1 wait()方法和notify()方法publicclassDemo_602{publicstaticvoidmain(String[]args){ObjectlockernewObject();Threadt1newThread(()-{while(true){System.out.println(调用wait之前....);synchronized(locker){try{locker.wait();}catch(InterruptedExceptione){thrownewRuntimeException(e);}}System.out.println(wait()唤醒之后...);System.out.println();}});Threadt2newThread(()-{while(true){System.out.println(调用notify之前....);synchronized(locker){locker.notify();}System.out.println(调用notify之后....);try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){thrownewRuntimeException(e);}}});t1.start();t2.start();}}7.3 notifyAll()方法notify唤醒一个线程notifyAlI唤醒所有线程全都再去竞争锁资源。总结wait 和 notify 必须搭配synchronized 一起使用。wait 和 notify 使用的锁对象必须是同一个。notify 执行多少次都没有关系即使没有线程在wait7.4 wait() 和 sleep() 的对比面试题其实理论上wait和sleep完全是没有可⽐性的因为⼀个是⽤于线程之间的通信的⼀个是让线程阻塞⼀段时间唯⼀的相同点就是都可以让线程放弃执⾏⼀段时间.当然为了⾯试的⽬的我们还是总结下wait需要搭配synchronized使⽤.sleep不需要join也不需要join是类中的方法。wait是Object的⽅法sleep是Thread的静态⽅法.