繁体   English   中英

java 同步监视器进入对非同步访问或非易失性变量的影响

[英]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易失的 booleanposition非易失的 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 的读/写操作,而是使用缓存值),如果我进入发生这种情况 1synchronized块(因为可能,更新的 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM