private static final long SEGSHIFT_OFFSET;
SEGSHIFT_OFFSET = UNSAFE.objectFieldOffset(
            ConcurrentHashMap.class.getDeclaredField("segmentShift"));
UNSAFE.putIntVolatile(this, SEGSHIFT_OFFSET, 32);


代码adove可以替换为以下代码吗?

private static volatile long SEGSHIFT_OFFSET = 0L;
SEGSHIFT_OFFSET = 32;


或可以替换如下?

private static synchronized long SEFSHIFT_OFFSET = 0L;
SEGSHIFT_OFFSET = 32;

最佳答案

我假设您在某些类的ConcurrentHashMap类中具有此代码。

不,您不能按照建议更换它。这段代码做的事情很危险:用新值更新segmentShift的程序包专用最终字段ConcurrentHashMapSEGSHIFT_OFFSET用于确定类中segmentShift字段在内存中的偏移量(此字段位置与对象开头之间的字节数)。由于此偏移量在JVM生命周期中假定为常数,因此将其存储在final字段中。

建议的替代方法完全不同:只声明该字段并更改其值。这样,您将无法更改不可访问的最终segmentShift字段的值。它使用易失性语义进行更新以在更新后放置内存屏障,因此其他线程将看到更新后的值(尽管我仍然怀疑这是否是一种健壮的方法)。

如果要替换此代码,则可以尝试use reflection,尽管这不会强加易变的语义,这在这种情况下可能是必需的。

请注意,由于ConcurrentHashMap的内部结构已发生重大变化且不再具有segmentShift字段,因此此不安全代码无法在JDK8中完全工作。如果您想升级到JDK8,那么反射也不会帮助您。

顺便说一句,关于完全删除Unsafeongoing discussion

关于java - volatile和UNSAFE.putIntVolatile()有什么区别,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31721917/

10-12 07:03