【发布时间】:2020-09-11 04:43:39
【问题描述】:
我有一个下载操作代码,看起来像这样
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 是一个易失性布尔值
position 是一个 non volatile long 值
在check() 方法中,我有一个synchronized 块
long check(){
//some code here
synchronized(aLock){
//some code here
return something;
}
}
我在这个线程中更新(写访问)positiononly(只关心这个是否有最新的更新)但也会发生来自不同线程的一些读取,我的情况只是用于监控目的
所以比我预期的要低几个字节,这与声明为 volatile 的值相比无关紧要,这会影响我的主要目的的性能
我知道 CPU 指令完成后,数据会在计算进度结果返回内存后到达 CPU 寄存器
哪个
- 如果该变量声明为volatile,则结果将立即写入主内存(不再缓存)
- 否则这将被存储在线程缓存内存中,之后这个值将被写入主内存(从缓存写入主内存,时间无法确定(这可以立即或延迟无人知道)我的情况我的问题是关于这种情况的价值 不是 volatile 和 only 在一个线程中
根据 StackOverflow 中一位亲爱的用户在 here 中的回答,当我们首先输入 synchronized 块时
(案例 1):我们有一个来自主内存的读操作(称为读屏障)
在synchronized 块的末尾
(案例 2):我们对主内存进行了写操作(称为写屏障)
我知道 案例 2
所有修改过的线程缓存变量都会写入主存
但我可能想错了,在 案例 1:
我们有一个来自主内存的读取操作,它使用存储在主内存中的版本覆盖线程的缓存。(main -> cache)
正如我之前提到的,我的 position 值是 not volatile(所以没有直接访问读/写到主内存使用缓存值),如果我输入 synchronized case 1 发生的块(因为可能,来自线程缓存的较新位置值还没有机会将其值写入主内存) 并将位置的主内存(可能是旧的)版本覆盖到线程缓存中(即通过覆盖通过同步monitor enter 操作检索到的旧值来销毁新的位置)
我真的这么想吗?
我是否必须将position 声明为volatile?
如果我错了,告诉我monitor enter(或我之前提到的 case 1 处的线程缓存中发生的事情)
提前感谢您的指导。
【问题讨论】:
-
I also update(write access) position only in this thread是在其他任何地方访问的位置,包括读取? -
after compution progress result will come back to memory嗯,不是真的。将结果保存在寄存器中并且不写回主内存是完全有效的。variable declared as volatile the result immediately will be written“使可见”与“写入主存”不同。可能是这样,但认为这种情况总是发生可能是危险的。otherwise this will be stored in thread cache memory可以被存储,但也不是 100% 保证的。东西往往不会被随机缓存,只是在你最意想不到的时候逃到野外。 -
你链接到的那个解释不是很好。规范实际上说的是在锁释放的结束 和锁获取的开始 之间存在happens-before 关系。
-
since that possible ,newer position value from thread's cache have not yet have chance to writes its value to main memory我不确定你在这里想说什么,但我认为答案是否定的,没有什么不好的事情发生。这就是试图说锁获取会创建读取障碍的麻烦,但事实并非如此。去阅读规范。它说单个线程访问的变量是线程安全的,句号。没有 happens-before 可以改变这一点。只要只有一个线程看到position就可以了。 -
@markspace
is position accessed anywhere else, including reads?是的,因为这个变量的主要目的是在这个线程中,并从其他线程读取只是为了监控 porposes,在这种情况下,我对几个字节或多或少不敏感跨度>
标签: java multithreading concurrency synchronization volatile