我想知道是否有任何方法可以在Java中使用Unsafe
(更准确地说是compareAndSwapObject
)对静态字段执行比较和交换操作。我尝试使用null
和类对象(TheClass.class
)作为第一个参数,但没有成功。
编辑:代码如下:
public class UnsafeTest
{
public static long staticField = 0;
public static void main(String[] args) throws Exception
{
Long l = 0L;
Long res = 350L;
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);
long off = unsafe.staticFieldOffset(
UnsafeTest.class.getDeclaredField("staticField"));
unsafe.compareAndSwapObject(UnsafeTest.class, off, l, res);
// null instead of UnsafeTest.class produces the same result
Thread.sleep(1000L);
System.out.println(staticField); // prints 0
}
}
我想让它对字段staticField
执行CAS,将其设置为350(任意值)。当在标准输出上打印其值时,它显示0;所以我想什么都没有改变,这两个都不是做我想做的事情的正确论据,假设这是可能的。
先谢谢你!
1条答案
按热度按时间py49o6xq1#
一个问题是,您在非引用类型的字段上使用
compareAndSwapObject
。由于该字段是long
,因此您应该使用compareAndSwapLong
。同样,
compareAndSwapXXX
方法返回一个boolean
来表示交换是成功还是失败。你应该检查它......是否有任何其他线程可能在同一个字段上执行CAS操作。(如果没有可能,就不要麻烦CAS了。只要使用常规赋值即可。)最后,我看了Java 8的源代码,我认为
Unsafe.compareAndSwapXxx
操作并不是设计来处理static
字段的,它使用Class
对象作为目标对象。相反,我认为您需要做如下操作:无论哪种方式,都不会检查
off
值对于执行CAS操作的对象的字段是否正确。因此,如果您出错,您可能会得到内存损坏(以及不正确的结果或JVM崩溃)...而不是一个干净的Java异常。这就是使用Unsafe
所冒的风险!上面已经说过了,任何使用
Unsafe
代码的代码都是不可移植的。而且您的代码在Java 9和更高版本中将失败,因为compareAndSwapXxx
方法已经被删除。在Java 9和更高版本中,正确的方法是使用
VarHandle
类;请参阅javadoc。