一个线程中多次使用共享变量,每一次使用都是从主存获取的吗?

比如:

 public class CountThread implements Runnable {
    private CountWorker countWorker;

    public CountThread(CountWorker countWorker) {
        this.countWorker = countWorker;
    }

    public void run() {
            System.out.println( Thread.currentThread().getName() + " get  sum is : " + countWorker.sum);
            countWorker.sum++;
        }
}

System.out的sum和执行sum++时的sum是打印时去主存获取一次然后sum++时去主存再获取一次吗?

4个回答

【1】countWorker.sum++;
,sum不是局部变量吧??。。。对象属性并非线程私有(线程中只存在引用),,对象内容存在堆中(这应当时题主说的共享内存)
按理说,,每次访问属性都应当去堆中(线程中没有)。。

【2】sum++并非一个操作,,解释请看:http://blog.csdn.net/a2796749/article/details/48193391
没记错的话,,volatile这个关键词貌似只对一个操作有效(sum++不适用),,参考这篇博客:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html

有问题还可以讨论,,,仅供参考,,我暂时是这样看的(日后遇到问题可能还会改变)

Small_Mouse0
鼠小 回复HLhakey: 深入理解Java虚拟机--周志明,,,你去看看这本书(我看了一点,大部分不好理解)
大约 3 年之前 回复
HLhakey
HLhakey 好的, 先谢过 . 比如这种每次去哪儿去取的这种 , 有理论支持吗? 或者参考文章有的话,更好. 谢谢哈.
大约 3 年之前 回复

在C中每次读数据, 每次读数据寄存去都会根据地址去存储中取数.但是有时候编译器会优化, 直接用寄存器里的值,而不是每次都去取....
所以C中最好加关键字 " volatile" (易变的) , 建议编译器每次去根据地址去取, 不要优化到直接用寄存器的值,防止脏数据.

JAVA大抵也应该类似,我记得也有 " volatile" , 具体的不甚了解, 主要从事C/C++

HLhakey
HLhakey 谢谢 , 讲得很好了. 有理论支持吗? 如果可以的话.
大约 3 年之前 回复
首先,不一定,这就是  countWorker.sum++;操作这行代码不能保证多线程环境下数据一致性的原因,即你的这段代码不是线程安全的。
其次,如果你的变量定义为volatile的话,可以保证每次变量一旦变化就强制写入内存中,但是还是无法保证 countWorker.sum++的原子性,
这一点可以参考鄙人的博客:http://blog.csdn.net/wojiushiwo945you/article/details/42553845
最后,如果工作中免不了多线程并发编程的话,建议系统看一下Java的内存模型JMM,了解级别的内存操作原则。
HLhakey
HLhakey 谢谢.
大约 3 年之前 回复

我记得是是这样的 ,obj.property 这种用法是从对象里面取出对应的属性,每一次都是从对象的内存中去取,这样会降低运行效率,所以在优化上是推荐多次使用的obj.property,先用临时变量保存,这样下次使用就不用再从对象中去取,从而提高了运行效率。

你这个例子不好,因为countWorker.sum++本身有操作,我改一下:

 public void run() {
                        // 临时变量保存
                        int num = countWorker.sum;
                        // 第一次使用num,用来打印
                        System.out.println( Thread.currentThread().getName() + " get  sum is : " + num);
                        // 第二次仅仅用来计算,因为使用的是临时变量,所以效率比下面这句要高
                        // System.out.println(“计算的结果是”+countWorker.sum + 1);
                        System.out.println(“计算的结果是”+num + 1);

   }
``
HLhakey
HLhakey 回复li504799868: 好的, 我明白你的意思 , 谢谢
大约 3 年之前 回复
u011315960
珠穆朗玛小王子 资料我也记不住了,你多看看一些有关优化的书或者资料吧,我举得这个例子仅仅是想说明局部变量的好处 ,如果你要操作对象内的属性,那肯定还得通过setter方法,这是两个问题。
大约 3 年之前 回复
HLhakey
HLhakey 您记得的那个.... 有相关材料支持吗? 还有, 您把sum值取出来赋值给局部变量然后再操作 , 是效率高,可是... sum的值没有变啊...
大约 3 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐