[英]Effect of java synchronized monitor enter on non synchronized access or not volatile variables
我有一个看起来像这样的下载操作代码
while(true){
if(target.flagStop){
break;
}else{
x=target.check();
}
len=in.read(buff,0,min(BUFFER_SIZE,x));
out.write(buff,0,len);
target.position+=len;
}
其中flagStop
是易失的 boolean和position
是非易失的 long值,在check()
方法中我有一个synchronized
块
long check(){
//some code here
synchronized(aLock){
//some code here
return something;
}
}
我只在这个线程中更新(写访问) position
(只关心这个是否有最新的更新)但也发生了来自不同线程的一些读取,我的情况只是出于监控目的,所以比我预期的要低几个字节与将价值声明为volatile
相比无关紧要,这在我的主要目的上会影响性能
我知道要完成一条 CPU 指令,计算进度结果将返回到 memory 后,数据到达 CPU 寄存器
- 如果该变量声明为volatile
,则结果将立即写入主 memory(不再缓存)
- 否则这将被存储在线程缓存 memory 之后,以后这个值将被写入主存储器(从缓存写入主 memory,时间无法确定(这可以立即或延迟无人知道)我的情况我的问题是关于这种情况,即价值不是volatile
的,而且只在一个线程中
根据 StackOverflow 中一位亲爱的用户的回答,当我们首先输入synchronized
块时
(案例 1):我们从主 memory 进行读取操作(称为读取屏障)
并在synchronized
块的末尾
(案例 2):我们对主 memory 进行了写操作(称为写屏障)
我知道案例2
所有修改过的线程缓存变量都将写入主 memory 但我可能认为错误的是情况 1:我们从主 memory 执行读取操作,它使用存储在主 ZCD69B4957F08CD861D 中的版本覆盖线程缓存(main -> cache)
正如我之前提到的,我的position
值不是volatile
的(因此不能直接访问对主 memory 的读/写操作,而是使用缓存值),如果我进入发生这种情况 1的synchronized
块(因为可能,更新的 Z4757FE07FD4982A86EEA6 来自线程缓存还没有机会将其值写入主内存)并将 position 的主内存(可能较旧)版本覆盖到线程缓存中(即通过覆盖同步monitor enter
操作检索到的旧值来销毁较新的)
我真的这么想吗?
我必须position
声明为volatile
吗?
并告诉我是否错了, monitor enter
时线程缓存中发生的事情(或我之前提到的案例 1 )提前感谢您的指导。
您正在寻找的部分内容:
https://docs.oracle.com/javase/specs/jls/se14/html/jls-17.html#jls-17.4.1
可以在线程之间共享的 Memory 称为共享 memory 或堆 memory。
所有实例字段、static 字段和数组元素都存储在堆 memory 中。 在本章中,我们使用术语变量来指代字段和数组元素。
局部变量(第 14.4 节)、形式方法参数(第 8.4.1 节)和异常处理程序参数(第 14.20 节)永远不会在线程之间共享,并且不受 memory model 的影响。
这里的“不受影响”意味着它们不需要同步。 只要只有一个线程看到一个变量,它总是没问题的。
这也有助于:
https://docs.oracle.com/javase/specs/jls/se14/html/jls-17.html#jls-17.4.7
执行遵循线程内一致性。
对于每个线程 t,t 在 A [由该线程执行的操作] 中执行的操作与该线程以程序顺序隔离生成的操作相同,每次写入 w 写入值 V(w),假设每个读取 r 会看到值 V(W(r))。 每次读取看到的值由 memory model 确定。 给定的程序顺序必须反映根据 P 的线程内语义执行动作的程序顺序。
操作意味着读取和写入。 所以你的变量position
因为同步而不允许用一些奇怪的值更新。 单个执行线程中的读取和写入按照程序语句指定的顺序发生。 系统不会从缓存或主 memory 乱序中拉出奇怪的读取或写入。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.