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 是一个 volatile 布尔值 position 是一个 非易失性 long 值 在 check() 方法中我有一个 synchronized

long check(){
  //some code here
  synchronized(aLock){
  //some code here
    return something;
  }
}

我在这个线程中更新(写入访问)position (只关心这个是最新更新的)但也有一些来自不同线程的读取,我的情况是这些仅用于监控目的 所以比我预期的低几个字节与将值声明为 volatile 无关紧要,这对我的主要目的

来说是性能成本

我知道一个CPU指令完成后数据来到CPU寄存器计算进度结果会回到内存 哪个
- 如果该变量声明为 volatile 结果将立即写入主内存(不再缓存)
- 否则这将被存储在线程缓存内存中,之后这个值将被写入主内存(从缓存写入主内存,时间无法确定(这可能是立即的或者有一个没有人知道的延迟)在我的情况我的问题是关于这种情况,即值 不是 volatile 并且 在一个线程中

根据 Whosebug 一位亲爱的用户在 here 中的回答,当我们首先进入 synchronized 块时
(案例 1): 我们有一个从主内存的读操作(称为读屏障)

并且在 synchronized 块的末尾
(案例 2): 我们对主存进行写操作(称为写屏障)

我知道 案例 2
所有修改过的线程缓存变量都会写入主存 但是我可能想错了 case 1: 我们有一个从主内存读取操作,它用存储在主内存中的版本覆盖线程的缓存。(main -> cache)

正如我之前提到的,我的 position 值是 而不是 volatile(所以没有直接访问 read/write 到主内存使用缓存值相反),如果我进入一个 synchronized 块,其中 情况 1 发生(因为那可能,更新 线程缓存中的位置值还没有机会将其值写入主内存)并将位置的主内存(可能是旧版本)版本覆盖到线程缓存中(即通过覆盖由同步 monitor enter 操作)
我真的这么想吗?
我是否必须将 position 声明为 volatile
并告诉我我之前提到的 monitor enter(或 case 1 线程缓存中发生的事情是否错误 预先感谢您的指导。

您要查找的部分内容:

https://docs.oracle.com/javase/specs/jls/se14/html/jls-17.html#jls-17.4.1

Memory that can be shared between threads is called shared memory or heap memory.

All instance fields, static fields, and array elements are stored in heap memory. In this chapter, we use the term variable to refer to both fields and array elements.

Local variables (§14.4), formal method parameters (§8.4.1), and exception handler parameters (§14.20) are never shared between threads and are unaffected by the memory model.

"Unaffected by"这里表示不需要同步。只要只有一个线程看到一个变量,就没问题。

这也有帮助:

https://docs.oracle.com/javase/specs/jls/se14/html/jls-17.html#jls-17.4.7

The execution obeys intra-thread consistency.

For each thread t, the actions performed by t in A [actions by that thread] are the same as would be generated by that thread in program-order in isolation, with each write w writing the value V(w), given that each read r sees the value V(W(r)). Values seen by each read are determined by the memory model. The program order given must reflect the program order in which the actions would be performed according to the intra-thread semantics of P.

操作意味着读取和写入。因此,由于同步,您的变量 position 不允许使用一些奇怪的值进行更新。单个执行线程中的读取和写入按照程序语句指定的相同顺序发生。系统不会乱序地从缓存或主内存中拉出奇怪的读取或写入。