Chinaunix首页 | 论坛 | 博客
  • 博客访问: 17451
  • 博文数量: 21
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 211
  • 用 户 组: 普通用户
  • 注册时间: 2015-12-09 16:47
文章分类

全部博文(21)

文章存档

2017年(1)

2016年(9)

2015年(11)

我的朋友
最近访客

分类: Java

2016-07-25 15:17:10

关键字volatile可以说是Java提供的最轻量级的同步机制。Java内存模型对volatile专门定义了一些特殊的访问规则。当一个变量被定义为volatile.它有以下两种特性,1:此变量对所有的线程具有可见性。即当一个线程改变变量的属性,对其他线程这个改变后的值是立即可知的。2:禁止指令重排序优化。

volatile变量并不能保证其在其变量在并发下是安全的。虽然其具有可见性,但是volatile变量在线程的内存并不存在一致性一说。虽然线程每次执行变量的时候都会重新刷新线程内存,但由于java里面的运算并非原子操作。导致volatile变量在并发情况下一样是不安全的。

public class VolatileTest {

   public static volatile int race =0;

   public  static void increas(){

      race++;

   }

   public static void main(String[] args) {

      Thread th[] = new Thread[20];

      for(int i=0;i<20;i++){

          th[i] = new Thread(new Runnable() {

             @Override

             public void run() {

                // TODO Auto-generated method stub

                for(int i=0;i<1000;i++){

                   increas();

                }

             }

          });

          th[i].start();

      }

      //等待所有线程都累加结束

      while(Thread.activeCount()>1){

          Thread.yield();

          System.out.print(race+"\n");

         

      }

     

     

   }

  

}

运行这段代码会发现输出的值每次都不相同,并且会小于20000。通过javap -verbose反编译

getstatic取到当前值的时候,但是并没有保证在执行iconst_1这条指令的时候,其他线程对变量已经执行加的操作了。由于volatile只能保证可见性,因此在不符合以下两种规则的时候我们任然需要加锁来保证原子性。

 

阅读(519) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~