06.volatile关键字

volatile

volatile关键字的主要作用是使变量在多个线程间可见

使用方法:

private volatile int number=0;

图示:

 两个线程t1和t2共享一份数据,int a=0,但是两个线程间是不可见的,t1修改a=10,但对于t2来说a还是从0变到20,两个线程是独立的,不可见的;

我想做的是a如果变化了,t1和t2实时的知道a变化了,即a不是从0变到20,而是从10变到20;即t1对a发生修改,t2实时知道a发生变化了;同理,t2中a变成20了,t1也能马上知道值变成20了;volatile关键字就能实现这个.

 运行结果如下:

 虽然输出了isRunning的值已经被设置成了false,但是线程仍然在运行;这是什么原因呢?

这是java  jdk的原因

java  jdk在执行一个程序时,都会分配一个单独的空间,但是在jdk1.5以后,它对每一个线程做了一个优化,对每个线程加了一块独立的运行空间,这块空间装主内存的一些引用(当前线程的一些引用变量),相当于拷贝了一份副本,线程运行时直接去副本取内容.这样做的目的是,让线程在执行时效率更高

 加volatile关键字后:

 这是为什么呢?

内存分析图:

 volatile只具有可见性不具备原子性(原子操作是不可分割的,在执行完毕不会被任何其它任务或事件中断)

总结:

volatile关键字虽然拥有多个线程之间的可见性,但是不具备同步性(也就是原子性),可以算上是一个轻量级的synchronized,性能要比synchronized强很多,不会造成阻塞(在很多开源的架构里,比如netty的底层就大量使用volatile,可见netty一定是非常不错的)

这里需要注意:一般volatile用于只针对于多个线程可见的变量操作,并不能代替synchronized的同步功能.

测试不具备原子性,例如:

 一个count,10个数组,每组加1000次,所以count结果应该为1000*10=10000

打印结果:

 说明volatile修饰不具备原子性.为啥呢??

第一个线程执行完1000,完了之后要打印,但是打印出来需要时间,在打印过程中,有可能第二个线程进去执行count++,所以打印出来的结果就如上图所示,但是观察最后一个线程,如果满足原子特性的化就一定是10000

如何保证原子性操作呢?

 使用AtomicInteger这个类,去多线程并发的原子操作,它有很多类型

 ======================================================================

示例总结:

 volatile关键字只具有可见性,没有原子性.要实现原子性建议使用atomic类的系列对象

原文地址:https://www.cnblogs.com/curedfisher/p/11983127.html