`

Unsafe

 
阅读更多

一.CAS(compare and swap) 

Unsafe 用于实现CAS(compare and swap) 操作,基于CPU一条原始指令,是原子的线程安全的,可用于多线程间非阻塞方式实现线程安全。

 

多线程中如果有多个线程修改共享变量,一般使用synchronized ,只有一个线程获得锁可以修改,其它线程阻塞等待锁释放, Unsafe.compareAndSwapXXX 使用比较再交换方式:

AbstractQueuedSynchronizer类中有实现:

private transient volatile Node tail;//volatile 用于可见性

private static final Unsafe unsafe = Unsafe.getUnsafe();//获取对象

 

static final long tailOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));//获取 AbstractQueuedSynchronizer对象 tail字段在内存中的相对偏移量,用于修改内存值

 

unsafe.compareAndSwapObject(this(  AbstractQueuedSynchronizer 对象), tailOffset, expect, update);//如果内存值与 expect值相同,则修改其值为 update新值。

线程安全性在于如果内存值与  expect值相同,则认为没有其它线程修改,则更新并返回真, 否则返回假compareAndSwapObject本身是原子的。所以线程是安全的。 

一般常用方法:

 public final long getAndSet(long newValue) {

        while (true) {//无限循环直至设置成功

            long current = get();//获取前值

            if (unsafe.compareAndSwapLong(this, valueOffset,  current newValue));//如果当前值与主内存值相等则设为新值。

                return current;

        }

    }

二.线程的挂起与恢复

 

Unsafe.park(Thread) //阻塞线程 

Unsafe.unPark(Thread) //唤醒线程,如果该线程未阻塞,该线程下次调用park方法时,直接返回,不阻塞。

 

线程池程序执行时,用jstack查看进程状态时,常看到Unsafe.park

 

 

 

/**
* 获取Unsafe对象
*
*/
public class AppUnsafeUtils {
    private static final Unsafe _unsafe;
    static{
        Unsafe temp= null;
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            temp= (Unsafe) field.get(null);
        }catch (Exception e){
            Throwables.propagate(e);
        }
        _unsafe = temp;
    }
    public static final Unsafe getUnsafe() {
        return _unsafe;
    }
}
 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics