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;
答案 0 :(得分:1)
我假设您在某个类中拥有此代码,该类是ConcurrentHashMap
类的子类。
不,它无法按照您的建议进行更换。此代码非常危险:它使用新值更新segmentShift
的包私有最终字段ConcurrentHashMap
。 SEGSHIFT_OFFSET
用于确定内存中segmentShift
字段的偏移量(此字段位置与对象开头之间的字节数)。由于此偏移在JVM生命周期中被假定为常量,因此它存储在最终字段中。
您建议的替换完全不同:只需声明字段并更改其值即可。这样您就无法更改无法访问的最终segmentShift
字段的值。它在更新后使用volatile语义更新内存屏障,因此其他线程将看到更新的值(尽管我仍然怀疑它是否是一种强大的方法)。
如果要替换此代码,可以尝试use reflection,尽管这不会强制使用在这种情况下可能需要的易失性语义。
请注意,这个不安全的代码在JDK8中无法完全发挥作用,因为ConcurrentHashMap
的内部结构发生了显着变化,并且不再有segmentShift
字段。如果你想升级到JDK8,那么反射也无济于事。
顺便提一下ongoing discussion关于完全删除Unsafe
。