Unsafe

java不能直接访问操作系统底层,而是通过本地方法来访问。Unsafe类提供了硬件级别的原子操作(直接引用网上的这句话,大致意思就是我们只能使用应用层的东西,然后应用层会去修改内存中对应的东西,也就是上面说的底层,但是我们一般是不能直接修改内存中东西的,如果人为的破坏了系统怎么办,这事一个安全问题)

线程的挂起与恢复

将一个线程进行挂起是通过park方法实现的,调用 park后,线程将一直阻塞直到超时或者中断等条件出现。unpark可以终止一个挂起的线程,使其恢复正常。整个并发框架中对线程的挂起操作被封装在 LockSupport类中,LockSupport类中有各种版本pack方法,但最终都调用了Unsafe.park()方法。

public class LockSupport {
    public static void unpark(Thread thread) {
        if (thread != null)
            unsafe.unpark(thread);
    }

    public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        unsafe.park(false, 0L);
        setBlocker(t, null);
    }

    public static void parkNanos(Object blocker, long nanos) {
        if (nanos > 0) {
            Thread t = Thread.currentThread();
            setBlocker(t, blocker);
            unsafe.park(false, nanos);
            setBlocker(t, null);
        }
    }

    public static void parkUntil(Object blocker, long deadline) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        unsafe.park(true, deadline);
        setBlocker(t, null);
    }

    public static void park() {
        unsafe.park(false, 0L);
    }

    public static void parkNanos(long nanos) {
        if (nanos > 0)
            unsafe.park(false, nanos);
    }

    public static void parkUntil(long deadline) {
        unsafe.park(true, deadline);
    }
}
CAS操作
/**
* 比较obj的offset处内存位置中的值和期望的值,如果相同则更新。此更新是不可中断的。
* 
* @param obj 需要更新的对象
* @param offset obj中整型field的偏移量
* @param expect 希望field中存在的值
* @param update 如果期望值expect与field的当前值相同,设置filed的值为这个新值
* @return 如果field的值被更改返回true
*/
public native boolean compareAndSwapInt(Object obj, long offset, int expect, int update);

这个方法相对来说看起来会熟悉一点

AbstractQueuedSynchronizer#compareAndSetTail

 private final boolean compareAndSetTail(Node expect, Node update) {
        return U.compareAndSwapObject(this, TAIL, expect, update);
    }

上面的方法是AbstractQueuedSynchronizer中修改队列队尾的CAS操作,参数如下:

Node expect 需要修改的对象中的某一个属性的预期值(也就是猜测这个属性现在的内存值是不是这个expect值)
Node update 需要修改的对象中的某一个属性需要被修改的指定值
TAIL 需要修改的对象中的某一属性对象
this 需要被修改的对象

我们先看下TAIL是怎么来的
AbstractQueuedSynchronizer的静态代码块中有这样的一段代码

    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
    private static final long STATE;
    private static final long HEAD;
    private static final long TAIL;

    static {
        try {
            STATE = U.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
            HEAD = U.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
            TAIL = U.objectFieldOffset
                (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
        } catch (ReflectiveOperationException e) {
            throw new Error(e);
        }

        // Reduce the risk of rare disastrous classloading in first call to
        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
        Class ensureLoaded = LockSupport.class;
    }

首先初始化Unsafe对象,然后定义了几个静态常量,这些静态常量的赋值是在静态代码块中,通过反射得到属性对应的属性对象,并传给U.objectFieldOffset并返回一个属性值,赋值给相应的属性,TAIL就是其中一个属性
所以上面AbstractQueuedSynchronizer修改队尾的操作完整的意义是:通过比较当前AbstractQueuedSynchronizer对象中的TAIL属性所对应的值是不是expect,如果是则将更新值updata作为一个新值赋值给TAIL属性,并返回true;如果TAIL对象的内存值不是expect,则不进行任何的赋值操作,最后返回false

下面是从网上找到的一份Unsafe源码 地址 感谢作者

package sun.misc;
import java.lang.reflect.Field;
/***
 * This class should provide access to low-level operations and its
 * use should be limited to trusted code.  Fields can be accessed using
 * memory addresses, with undefined behaviour occurring if invalid memory
 * addresses are given.
 * 这个类提供了一个更底层的操作并且应该在受信任的代码中使用。可以通过内存地址
 * 存取fields,如果给出的内存地址是无效的那么会有一个不确定的运行表现。
 * 
 * @author Tom Tromey ([email protected])
 * @author Andrew John Hughes ([email protected])
 */
public class Unsafe
{
  // Singleton class.
  private static Unsafe unsafe = new Unsafe();
  /***
   * Private default constructor to prevent creation of an arbitrary
   * number of instances.
   * 使用私有默认构造器防止创建多个实例
   */
  private Unsafe()
  {
  }
  /***
   * Retrieve the singleton instance of Unsafe.  The calling
   * method should guard this instance from untrusted code, as it provides
   * access to low-level operations such as direct memory access.
   * 获取Unsafe的单例,这个方法调用应该防止在不可信的代码中实例,
   * 因为unsafe类提供了一个低级别的操作,例如直接内存存取。
   * 
   * @throws SecurityException if a security manager exists and prevents
   *                           access to the system properties.
   *                           如果安全管理器不存在或者禁止访问系统属性
   */
  public static Unsafe getUnsafe()
  {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      sm.checkPropertiesAccess();
    return unsafe;
  }
  
  /***
   * Returns the memory address offset of the given static field.
   * The offset is merely used as a means to access a particular field
   * in the other methods of this class.  The value is unique to the given
   * field and the same value should be returned on each subsequent call.
   * 返回指定静态field的内存地址偏移量,在这个类的其他方法中这个值只是被用作一个访问
   * 特定field的一个方式。这个值对于 给定的field是唯一的,并且后续对该方法的调用都应该
   * 返回相同的值。
   *
   * @param field the field whose offset should be returned.
   *              需要返回偏移量的field
   * @return the offset of the given field.
   *         指定field的偏移量
   */
  public native long objectFieldOffset(Field field);
  /***
   * Compares the value of the integer field at the specified offset
   * in the supplied object with the given expected value, and updates
   * it if they match.  The operation of this method should be atomic,
   * thus providing an uninterruptible way of updating an integer field.
   * 在obj的offset位置比较integer field和期望的值,如果相同则更新。这个方法
   * 的操作应该是原子的,因此提供了一种不可中断的方式更新integer field。
   * 
   * @param obj the object containing the field to modify.
   *            包含要修改field的对象
   * @param offset the offset of the integer field within obj.
   *               obj中整型field的偏移量
   * @param expect the expected value of the field.
   *               希望field中存在的值
   * @param update the new value of the field if it equals expect.
   *           如果期望值expect与field的当前值相同,设置filed的值为这个新值
   * @return true if the field was changed.
   *                             如果field的值被更改
   */
  public native boolean compareAndSwapInt(Object obj, long offset,
                                          int expect, int update);
  /***
   * Compares the value of the long field at the specified offset
   * in the supplied object with the given expected value, and updates
   * it if they match.  The operation of this method should be atomic,
   * thus providing an uninterruptible way of updating a long field.
   * 在obj的offset位置比较long field和期望的值,如果相同则更新。这个方法
   * 的操作应该是原子的,因此提供了一种不可中断的方式更新long field。
   * 
   * @param obj the object containing the field to modify.
   *              包含要修改field的对象 
   * @param offset the offset of the long field within obj.
   *               obj中long型field的偏移量
   * @param expect the expected value of the field.
   *               希望field中存在的值
   * @param update the new value of the field if it equals expect.
   *               如果期望值expect与field的当前值相同,设置filed的值为这个新值
   * @return true if the field was changed.
   *              如果field的值被更改
   */
  public native boolean compareAndSwapLong(Object obj, long offset,
                                           long expect, long update);
  /***
   * Compares the value of the object field at the specified offset
   * in the supplied object with the given expected value, and updates
   * it if they match.  The operation of this method should be atomic,
   * thus providing an uninterruptible way of updating an object field.
   * 在obj的offset位置比较object field和期望的值,如果相同则更新。这个方法
   * 的操作应该是原子的,因此提供了一种不可中断的方式更新object field。
   * 
   * @param obj the object containing the field to modify.
   *    包含要修改field的对象 
   * @param offset the offset of the object field within obj.
   *         obj中object型field的偏移量
   * @param expect the expected value of the field.
   *               希望field中存在的值
   * @param update the new value of the field if it equals expect.
   *               如果期望值expect与field的当前值相同,设置filed的值为这个新值
   * @return true if the field was changed.
   *              如果field的值被更改
   */
  public native boolean compareAndSwapObject(Object obj, long offset,
                                             Object expect, Object update);
  /***
   * Sets the value of the integer field at the specified offset in the
   * supplied object to the given value.  This is an ordered or lazy
   * version of putIntVolatile(Object,long,int), which
   * doesn't guarantee the immediate visibility of the change to other
   * threads.  It is only really useful where the integer field is
   * volatile, and is thus expected to change unexpectedly.
   * 设置obj对象中offset偏移地址对应的整型field的值为指定值。这是一个有序或者
   * 有延迟的putIntVolatile方法,并且不保证值的改变被其他线程立
   * 即看到。只有在field被volatile修饰并且期望被意外修改的时候
   * 使用才有用。
   * 
   * @param obj the object containing the field to modify.
   *    包含需要修改field的对象
   * @param offset the offset of the integer field within obj.
   *       obj中整型field的偏移量
   * @param value the new value of the field.
   *      field将被设置的新值
   * @see #putIntVolatile(Object,long,int)
   */
  public native void putOrderedInt(Object obj, long offset, int value);
  /***
   * Sets the value of the long field at the specified offset in the
   * supplied object to the given value.  This is an ordered or lazy
   * version of putLongVolatile(Object,long,long), which
   * doesn't guarantee the immediate visibility of the change to other
   * threads.  It is only really useful where the long field is
   * volatile, and is thus expected to change unexpectedly.
   * 设置obj对象中offset偏移地址对应的long型field的值为指定值。这是一个有序或者
   * 有延迟的putLongVolatile方法,并且不保证值的改变被其他线程立
   * 即看到。只有在field被volatile修饰并且期望被意外修改的时候
   * 使用才有用。
   * 
   * @param obj the object containing the field to modify.
   *    包含需要修改field的对象
   * @param offset the offset of the long field within obj.
   *       obj中long型field的偏移量
   * @param value the new value of the field.
   *      field将被设置的新值
   * @see #putLongVolatile(Object,long,long)
   */
  public native void putOrderedLong(Object obj, long offset, long value);
  /***
   * Sets the value of the object field at the specified offset in the
   * supplied object to the given value.  This is an ordered or lazy
   * version of putObjectVolatile(Object,long,Object), which
   * doesn't guarantee the immediate visibility of the change to other
   * threads.  It is only really useful where the object field is
   * volatile, and is thus expected to change unexpectedly.
   * 设置obj对象中offset偏移地址对应的object型field的值为指定值。这是一个有序或者
   * 有延迟的putObjectVolatile方法,并且不保证值的改变被其他线程立
   * 即看到。只有在field被volatile修饰并且期望被意外修改的时候
   * 使用才有用。
   *
   * @param obj the object containing the field to modify.
   *    包含需要修改field的对象
   * @param offset the offset of the object field within obj.
   *       obj中long型field的偏移量
   * @param value the new value of the field.
   *      field将被设置的新值
   */
  public native void putOrderedObject(Object obj, long offset, Object value);
  /***
   * Sets the value of the integer field at the specified offset in the
   * supplied object to the given value, with volatile store semantics.
   * 设置obj对象中offset偏移地址对应的整型field的值为指定值。支持volatile store语义
   * 
   * @param obj the object containing the field to modify.
   *    包含需要修改field的对象
   * @param offset the offset of the integer field within obj.
   *       obj中整型field的偏移量
   * @param value the new value of the field.
   *       field将被设置的新值
   */
  public native void putIntVolatile(Object obj, long offset, int value);
  /***
   * Retrieves the value of the integer field at the specified offset in the
   * supplied object with volatile load semantics.
   * 获取obj对象中offset偏移地址对应的整型field的值,支持volatile load语义。
   * 
   * @param obj the object containing the field to read.
   *    包含需要去读取的field的对象
   * @param offset the offset of the integer field within obj.
   *       obj中整型field的偏移量
   */
  public native int getIntVolatile(Object obj, long offset);
  /***
   * Sets the value of the long field at the specified offset in the
   * supplied object to the given value, with volatile store semantics.
   * 设置obj对象中offset偏移地址对应的long型field的值为指定值。支持volatile store语义
   *
   * @param obj the object containing the field to modify.
   *            包含需要修改field的对象
   * @param offset the offset of the long field within obj.
   *               obj中long型field的偏移量
   * @param value the new value of the field.
   *              field将被设置的新值
   * @see #putLong(Object,long,long)
   */
  public native void putLongVolatile(Object obj, long offset, long value);
  /***
   * Sets the value of the long field at the specified offset in the
   * supplied object to the given value.
   * 设置obj对象中offset偏移地址对应的long型field的值为指定值。
   * 
   * @param obj the object containing the field to modify.
   *     包含需要修改field的对象
   * @param offset the offset of the long field within obj.
   *     obj中long型field的偏移量
   * @param value the new value of the field.
   *     field将被设置的新值
   * @see #putLongVolatile(Object,long,long)
   */
  public native void putLong(Object obj, long offset, long value);
  /***
   * Retrieves the value of the long field at the specified offset in the
   * supplied object with volatile load semantics.
   * 获取obj对象中offset偏移地址对应的long型field的值,支持volatile load语义。
   * 
   * @param obj the object containing the field to read.
   *    包含需要去读取的field的对象
   * @param offset the offset of the long field within obj.
   *       obj中long型field的偏移量
   * @see #getLong(Object,long)
   */
  public native long getLongVolatile(Object obj, long offset);
  /***
   * Retrieves the value of the long field at the specified offset in the
   * supplied object.
   * 获取obj对象中offset偏移地址对应的long型field的值
   * 
   * @param obj the object containing the field to read.
   *    包含需要去读取的field的对象
   * @param offset the offset of the long field within obj.
   *       obj中long型field的偏移量
   * @see #getLongVolatile(Object,long)
   */
  public native long getLong(Object obj, long offset);
  /***
   * Sets the value of the object field at the specified offset in the
   * supplied object to the given value, with volatile store semantics.
   * 设置obj对象中offset偏移地址对应的object型field的值为指定值。支持volatile store语义
   * 
   * @param obj the object containing the field to modify.
   *    包含需要修改field的对象
   * @param offset the offset of the object field within obj.
   *     obj中object型field的偏移量
   * @param value the new value of the field.
   *       field将被设置的新值
   * @see #putObject(Object,long,Object)
   */
  public native void putObjectVolatile(Object obj, long offset, Object value);
  /***
   * Sets the value of the object field at the specified offset in the
   * supplied object to the given value.
   * 设置obj对象中offset偏移地址对应的object型field的值为指定值。
   * 
   * @param obj the object containing the field to modify.
   *    包含需要修改field的对象
   * @param offset the offset of the object field within obj.
   *     obj中object型field的偏移量
   * @param value the new value of the field.
   *       field将被设置的新值
   * @see #putObjectVolatile(Object,long,Object)
   */
  public native void putObject(Object obj, long offset, Object value);
  /***
   * Retrieves the value of the object field at the specified offset in the
   * supplied object with volatile load semantics.
   * 获取obj对象中offset偏移地址对应的object型field的值,支持volatile load语义。
   * 
   * @param obj the object containing the field to read.
   *    包含需要去读取的field的对象
   * @param offset the offset of the object field within obj.
   *       obj中object型field的偏移量
   */
  public native Object getObjectVolatile(Object obj, long offset);
  /***
   * Returns the offset of the first element for a given array class.
   * To access elements of the array class, this value may be used along with
   * with that returned by 
   * arrayIndexScale,
   * if non-zero.
   * 获取给定数组中第一个元素的偏移地址。
   * 为了存取数组中的元素,这个偏移地址与arrayIndexScale
   * 方法的非0返回值一起被使用。
   * @param arrayClass the class for which the first element's address should
   *                   be obtained.
   *                   第一个元素地址被获取的class
   * @return the offset of the first element of the array class.
   *    数组第一个元素 的偏移地址
   * @see arrayIndexScale(Class)
   */
  public native int arrayBaseOffset(Class arrayClass);
  /***
   * Returns the scale factor used for addressing elements of the supplied
   * array class.  Where a suitable scale factor can not be returned (e.g.
   * for primitive types), zero should be returned.  The returned value
   * can be used with 
   * arrayBaseOffset
   * to access elements of the class.
   * 获取用户给定数组寻址的换算因子.一个合适的换算因子不能返回的时候(例如:基本类型),
   * 返回0.这个返回值能够与arrayBaseOffset
   * 一起使用去存取这个数组class中的元素
   * 
   * @param arrayClass the class whose scale factor should be returned.
   * @return the scale factor, or zero if not supported for this array class.
   */
  public native int arrayIndexScale(Class arrayClass);
  
  /***
   * Releases the block on a thread created by 
   * park.  This method can also be used
   * to terminate a blockage caused by a prior call to park.
   * This operation is unsafe, as the thread must be guaranteed to be
   * live.  This is true of Java, but not native code.
   * 释放被park创建的在一个线程上的阻塞.这个
   * 方法也可以被使用来终止一个先前调用park导致的阻塞.
   * 这个操作操作时不安全的,因此线程必须保证是活的.这是java代码不是native代码。
   * @param thread the thread to unblock.
   *           要解除阻塞的线程
   */
  public native void unpark(Thread thread);
  /***
   * Blocks the thread until a matching 
   * unpark occurs, the thread is
   * interrupted or the optional timeout expires.  If an unpark
   * call has already occurred, this also counts.  A timeout value of zero
   * is defined as no timeout.  When isAbsolute is
   * true, the timeout is in milliseconds relative to the
   * epoch.  Otherwise, the value is the number of nanoseconds which must
   * occur before timeout.  This call may also return spuriously (i.e.
   * for no apparent reason).
   * 阻塞一个线程直到unpark出现、线程
   * 被中断或者timeout时间到期。如果一个unpark调用已经出现了,
   * 这里只计数。timeout为0表示永不过期.当isAbsolute为true时,
   * timeout是相对于新纪元之后的毫秒。否则这个值就是超时前的纳秒数。这个方法执行时
   * 也可能不合理地返回(没有具体原因)
   * 
   * @param isAbsolute true if the timeout is specified in milliseconds from
   *                   the epoch.
   *                   如果为true timeout的值是一个相对于新纪元之后的毫秒数
   * @param time either the number of nanoseconds to wait, or a time in
   *             milliseconds from the epoch to wait for.
   *             可以是一个要等待的纳秒数,或者是一个相对于新纪元之后的毫秒数直到
   *             到达这个时间点
   */
  public native void park(boolean isAbsolute, long time);
}

功能大概包括比较修改属性值、直接修改属性值、获取属性值,还有上面说的线程的挂起

你可能感兴趣的:(Unsafe)