在看 Java并发包(java.util.concurrent)中大量使用了CAS操作,CAS即 Compare And Swap(CAS),比较并交换,其中由sun.misc.Unsafe实现,Unsafe类提供了硬件级别的原子操作,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。具体实现使用c++。 牛B,**Unsafe类提供了硬件级别的原子操作**,但到底是什么意思呢?CAS从字面意思上就有两部分:1、读取并比较;2、判断并决定是否交换。然后把这两步骤作为原子操作,这样就能保证线程安全
几句关于
Unsafe的并发性。compareAndSwap方法是
原子的,并且可用来实现高性能的、无锁的数据结构。比如,考虑问题:在使用大量线程的共享对象上增长值。...
Java是一门安全的编程语言,防止程序员犯很多愚蠢的错误,它们大部分是基于内存管理的。但是,有一种方式可以有意的执行一些不安全、容易犯错的操作,那就是使用
Unsafe
类。
CAS操作有3个操作数,内存值M,预期值E,新值U,如果M==E,则将内存值修改为B,否则啥都不做。
sun.misc.Unsafe这个类是如此地不安全,以至于JDK开发者增加了很多特殊限制来访问它。它的构造器是私有的,工厂方法
getUnsafe()的调用器只能被Bootloader加载。如你在下面代码片段的第8行所见,这个家伙甚至没有被任何类加载器加载,所以它的类加载器是
null。它会抛出
SecurityException 异常来阻止侵入者。
public final class Unsafe {
...
private Unsafe() {}
private static final Unsafe theUnsafe = new Unsafe();
...
public static Unsafe getUnsafe() {
Class cc = sun.reflect.Reflection.getCallerClass(2);
if (cc.getClassLoader() != null)
throw new SecurityException("Unsafe");
return theUnsafe;
}
...
public
static
Unsafe getUnsafe() {
try
{
Field f = Unsafe.
class
.getDeclaredField(
"theUnsafe"
);
f.setAccessible(
true
);
return
(Unsafe)f.get(
null
);
}
catch
(Exception e) {
/* ... */
}
}
Unsafe一些有用的特性
- 虚拟机“集约化”(VM intrinsification):如用于无锁Hash表中的CAS(比较和交换)。再比如compareAndSwapInt这个方法用JNI调用,包含了对CAS有特殊引导的本地代码。在这里你能读到更多关于CAS的信息:http://en.wikipedia.org/wiki/Compare-and-swap。
- 主机虚拟机(译注:主机虚拟机主要用来管理其他虚拟机。而虚拟平台我们看到只有guest VM)的sun.misc.Unsafe功能能够被用于未初始化的对象分配内存(用allocateInstance方法),然后将构造器调用解释为其他方法的调用。
- 你可以从本地内存地址中追踪到这些数据。使用java.lang.Unsafe类获取内存地址是可能的。而且可以通过unsafe方法直接操作这些变量!
- 使用allocateMemory方法,内存可以被分配到堆外。例如当allocateDirect方法被调用时DirectByteBuffer构造器内部会使用allocateMemory。
- arrayBaseOffset和arrayIndexScale方法可以被用于开发arraylets,一种用来将大数组分解为小对象、限制扫描的实时消耗或者在大对象上做更新和移动。
Unsafe.java是jdk并发类库java.util.concurrent包中使用的底层类,该类中的方法都是通过native方法调用操作系统命令。
在多线程环境下,主要存在两种特殊的场景:
1;多个线程同时访问某个对象的方法,由于操作系统对线程调度的不确定性,存在使该对象的状态处于不一致的状态,为了避免这种情况的发生,我们可以声明该方法为同步方法(synchronized)。保证某一时刻只有一个线程调用该方法,其它调用线程则被阻塞。这种方法在并发性很高的情况下会产生大量的线程调度开销。从而影响程序的并发性能。在java.util.concurrent包中通过使用非阻塞原子方法,减少操作系统的无用线程调度开销,从而提高并发性能。
2;多线程通过某个对象进行通信,即常见的生产者消费者模型。在以前的jdk版本中是通过wait,notify方法实现的。该方法也是通过底层在某个信号量上的阻塞队列实现的。而Unsafe类中直接提供操作系统调度命令park,unpark,减少信号量的开销,提高新能。
从上面可以看出,Unsafe类是通过提供底层的操作系统命令接口给开发者,从而提供程序的性能。