DD.*_*DD. 58 java synchronized
private double value;
public synchronized void setValue(double value) {
this.value = value;
}
public double getValue() {
return this.value;
}
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,让getter同步有什么意义吗?
Kon*_*che 76
我认为最好在这里引用Java Concurrency in Practice:
假设只有在写入共享变量时才需要使用同步,这是一个常见的错误.这是不正确的.
对于可由多个线程访问的每个可变状态变量,必须在保持相同锁的情况下执行对该变量的所有访问.在这种情况下,我们说该变量由该锁保护.
在没有同步的情况下,编译器,处理器和运行时可以对操作看起来执行的顺序做一些彻头彻尾的奇怪事情.尝试推断在不充分同步的多线程程序中"必须"发生内存操作的顺序几乎肯定是不正确的.
通常情况下,您不必非常小心原语,所以如果这是一个int或者boolean它可能是这样:
当一个线程在没有同步的情况下读取一个变量时,它可能会看到一个陈旧的值,但至少它会看到某个线程实际放置的值而不是某个随机值.
但是,这不适用于64位操作,例如on long或者double如果未声明它们volatile:
Java内存模型要求获取和存储操作是原子操作,但对于非易失性长和双变量,JVM允许将64位读或写视为两个独立的32位操作.如果读取和写入发生在不同的线程中,则可以读取非易失性long并返回一个值的高32位和另一个值的低32位.
因此,即使您不关心陈旧值,在多线程程序中使用共享的可变长和双变量也是不安全的,除非它们被声明为volatile或由锁保护.
Mar*_*nik 18
让我通过示例向您展示JIT编译代码的合法方式.你写:
while (myBean.getValue() > 1.0) {
// perform some action
Thread.sleep(1);
}
Run Code Online (Sandbox Code Playgroud)
JIT编译:
if (myBean.getValue() > 1.0)
while (true) {
// perform some action
Thread.sleep(1);
}
Run Code Online (Sandbox Code Playgroud)
在稍微不同的场景中,即使Java编译器也可以产生类似的字节码(它只需要消除动态调度到不同的可能性getValue).这是一个提升的教科书例子.
为什么合法?编译器有权假设myBean.getValue()执行上述代码时结果永远不会改变.如果没有synchronized它,则允许忽略其他线程的任何操作.
| 归档时间: |
|
| 查看次数: |
26784 次 |
| 最近记录: |