在阅读JSR-133 Cookbook for Compiler Writers关于volatile的实现之后,特别是"与原子指令的交互"部分我认为读取volatile变量而不更新它需要LoadLoad或LoadStore屏障.在页面的下方,我看到LoadLoad和LoadStore在X86 CPU上实际上是无操作的.这是否意味着可以在x86上没有显式缓存失效的情况下完成易失性读取操作,并且正常变量读取速度快(忽略volatile的重新排序约束)?
我相信我不明白这一点.有人可以照顾我吗?
编辑:我想知道多处理器环境是否存在差异.在单CPU系统上,CPU可能会查看它自己的线程缓存,正如John V.所述,但在多CPU系统上,CPU必须有一些配置选项,这是不够的,主内存必须被击中,使得波动较慢在多CPU系统上,对吗?
PS:在我学习更多相关信息的路上,我偶然发现了以下很棒的文章,因为这个问题可能对其他人很有意思,我会在这里分享我的链接:
这是Java Concurrency in Practice中的一句话
共享只读对象包括不可变和有效不可变对象.
不可变和有效不可变对象之间有什么区别?
当我阅读 Brian Goetz 的《Java 并发实践》时,我记得他在有关可见性的章节中说过“另一方面,即使不使用同步来发布对象引用,也可以安全地访问不可变对象”。
我认为这意味着,如果您发布一个不可变的对象,则所有字段(包括可变的最终引用)对于可能使用它们的其他线程都是可见的,并且至少是该对象完成构造时的最新状态。
现在,我在https://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html中读到“现在,说了所有这些,如果在线程构造一个不可变对象之后(即,仅包含最终字段的对象),如果您想确保所有其他线程都能正确看到它,那么通常仍然需要使用同步。没有其他方法可以确保,例如,第二个线程将看到对不可变对象的引用。程序从最终字段获得的保证应该通过深入而仔细地理解代码中如何管理并发性来仔细调整。
他们似乎互相矛盾,我不知道该相信哪一个。
我还读到,如果所有字段都是最终字段,那么即使对象本身不是不可变的,我们也可以确保安全发布。例如,由于这个保证,在发布此类的对象时,我一直认为实践中 Brian Goetz 的并发中的这段代码是没问题的。
@ThreadSafe
public class MonitorVehicleTracker {
@GuardedBy("this")
private final Map<String, MutablePoint> locations;
public MonitorVehicleTracker(
Map<String, MutablePoint> locations) {
this.locations = deepCopy(locations);
}
public synchronized Map<String, MutablePoint> getLocations() {
return deepCopy(locations);
}
public synchronized MutablePoint getLocation(String id) {
MutablePoint loc = locations.get(id);
return loc == null ? null : new MutablePoint(loc);
}
public synchronized void setLocation(String id, int x, int y) {
MutablePoint loc = locations.get(id);
if (loc …Run Code Online (Sandbox Code Playgroud) concurrency multithreading visibility immutability thread-safety