比如:
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++时去主存再获取一次吗?
【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
有问题还可以讨论,,,仅供参考,,我暂时是这样看的(日后遇到问题可能还会改变)
在C中每次读数据, 每次读数据寄存去都会根据地址去存储中取数.但是有时候编译器会优化, 直接用寄存器里的值,而不是每次都去取....
所以C中最好加关键字 " volatile" (易变的) , 建议编译器每次去根据地址去取, 不要优化到直接用寄存器的值,防止脏数据.
JAVA大抵也应该类似,我记得也有 " volatile" , 具体的不甚了解, 主要从事C/C++
首先,不一定,这就是 countWorker.sum++;操作这行代码不能保证多线程环境下数据一致性的原因,即你的这段代码不是线程安全的。
其次,如果你的变量定义为volatile的话,可以保证每次变量一旦变化就强制写入内存中,但是还是无法保证 countWorker.sum++的原子性,
这一点可以参考鄙人的博客:http://blog.csdn.net/wojiushiwo945you/article/details/42553845
最后,如果工作中免不了多线程并发编程的话,建议系统看一下Java的内存模型JMM,了解级别的内存操作原则。
我记得是是这样的 ,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);
}
``
不是,是读的工作内存的,而不是主内存的。一个线程从主内存中读取一次后,拷贝主内存变量在工作内存中,下次使用直接取工作内存的而不是主内存的。这是线程间的不可见性。如果每次都能立马刷新主内存,立马读取主内存,要volatile有啥用?
这样volatile关键字才有了用武之地,根据EMSI强制刷新主内存中的变量到每个线程的工作内存中,保证了可见性。即线程A和B从主内存载入变量i,A修改变量i会设置状态为M(修改),B中的i设置状态为I(无效),B重新载入主内存的i。