我们知道,一些JIT允许重新排序对象初始化,例如,
someRef = new SomeObject();
Run Code Online (Sandbox Code Playgroud)
可以分解为以下步骤:
objRef = allocate space for SomeObject; //step1
call constructor of SomeObject; //step2
someRef = objRef; //step3
Run Code Online (Sandbox Code Playgroud)
JIT编译器可能会重新排序如下:
objRef = allocate space for SomeObject; //step1
someRef = objRef; //step3
call constructor of SomeObject; //step2
Run Code Online (Sandbox Code Playgroud)
即,步骤2和步骤3可以由JIT编译器重新排序.虽然这在理论上是有效的重新排序,但我无法使用x86平台下的Hotspot(jdk1.7)重现它.
那么,Hotspot JIT comipler是否可以重现任何指令重新排序?
更新:我使用以下命令在我的机器(Linux x86_64,JDK 1.8.0_40,i5-3210M)上进行了测试:
java -XX:-UseCompressedOops -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand="print org.openjdk.jcstress.tests.unsafe.UnsafePublication::publish" -XX:CompileCommand="inline, org.openjdk.jcstress.tests.unsafe.UnsafePublication::publish" -XX:PrintAssemblyOptions=intel -jar tests-custom/target/jcstress.jar -f -1 -t .*UnsafePublication.* -v > log.txt
Run Code Online (Sandbox Code Playgroud)
我可以看到该工具报告的内容如下:
[1] 5可接受对象已发布,至少有1个字段可见.
这意味着观察者线程看到了一个未初始化的MyObject实例.
但是,我没有看到像@ Ivan那样生成的汇编代码:
0x00007f71d4a15e34: mov r11d,DWORD PTR …Run Code Online (Sandbox Code Playgroud) 我正在浏览ConcurrentHashMapjdk 7中的源代码并且几乎没有问题.我已经在StackOverFlow上完成了有关CHM的所有问题,但找不到答案.
get()CHM中的操作是否保证put()由其他线程获得正确的值?我问这是因为get不是,synchronized除非它看到null值.null值如何确保其他线程正在更新相同的记录然后get与lock一起使用?
这与HashEntry存储键和值的静态类有关.
一个.为什么这堂课最后?它只是为了确保没有人对它进行子类化吗?如果有人将其子类化,会发生什么 - 这有什么问题?
湾 如何使下一个字段最终有助于获得线程安全?
C.为什么Key也是最终的?(我不确定为什么Key也是最终的HashMap)
java collections multithreading concurrenthashmap java.util.concurrent
我在我的一个应用程序中编写了类似的代码,但我不确定它是否是线程安全的.
public class MyClass {
private MyObject myObject = new MyObject();
public void setObject(MyObject o) {
myObject = o;
}
public MyObject getObject() {
return myObject;
}
}
Run Code Online (Sandbox Code Playgroud)
该setObject()和getObject()方法将通过不同的线程调用.该getObject()方法将由持续绘制Canvas的线程调用.为了获得最佳FPS和平滑运动,我不希望该线程一直等待同步锁定.因此,除非确实有必要,否则我希望避免使用同步.那么这里真的有必要吗?或者还有其他更好的方法来解决这个问题吗?
顺便说一句,线程是否收到对象的旧副本并不重要.