zoukankan      html  css  js  c++  java
  • volatile关键字 学习记录2

     1 public class VolatileTest2 implements Runnable{
     2     volatile int resource = 0;
     3     
     4     public static void main(String[] args) {
     5         VolatileTest2 vt = new VolatileTest2();
     6         new Thread(vt).start();
     7         new Thread(vt).start();
     8         while(Thread.activeCount() > 1){
     9             Thread.yield();
    10         }
    11         System.out.println(vt.resource);
    12     }
    13 
    14     @Override
    15     public void run() {
    16         for(int i=0; i<100000000; i++){
    17             resource++;
    18         }
    19     }
    20 }

    这个例子中虽然resource前面有volatile关键字,但是运行结果有时候仍然不是200000000..为什么呢? 我想分享下我的观点.

    首先每个线程有自己的内存,他们修改resource的时候会先把数据拷贝到自己的内存中,再修改,再写回主内存..所以如果是这样的话那么多个线程同时操作可能会有很多种情况,下面举2种情况

    (不加volatile关键字的时候会出现的N种情况中的2种)

    第一种情况:

    第二种情况

    上面2种情况都会使t2线程把resource写回主内存的时候把t1自增那次操作覆盖掉.因为t1与t2线程读主内存的resource的值是一样的...所以相当于t1的自增是无效的.

    当resource前面加了volatile关键字的时候:

    用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最新的值。

    http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html

    所以加了这个关键字以后是可以避免第二种情况的.

    t1 resource自增以后会直接写回主内存,使t2读取操作读取到的是最新的值.相当于resource++与写回主内存是同一个事务,不可以分隔.

    但是仍然不能避免第一种情况的发生.

    在第一种情况下,线程t2 读取resource是发生在t1 resource自增之前的,所以当t1 自增以后并不会影响t2线程内存中的resource,因为这并不违背volatile.如果此时t2再去读取resource那才是最新的值.不过可惜他在t1自增之前就读取了,所以t2中resource的值仍然是旧的.当t2写回主内存的时候仍然会覆盖t1自增的值.

    以上就是我的理解.

  • 相关阅读:
    C++中的friend函数详细解析(一)
    【图像处理算法】 直方图均衡化
    可降水量W:空中水文学名词初集(4)
    excel\docx
    WebService学习总结
    C#深入学习笔记Lock
    事件Event深入总结
    C#泛型委托与Lambda总结
    SQLServer事务与锁的基础概念总结
    委托Delegate深入总结
  • 原文地址:https://www.cnblogs.com/abcwt112/p/5150470.html
Copyright © 2011-2022 走看看