Unsafe对象
Unsafe 对象提供了非常底层的,操作内存、线程的方法,Unsafe 对象不能直接调用,只能通过反射获得
public class UnsafeAccessor { static Unsafe unsafe; static { try { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); unsafe = (Unsafe) theUnsafe.get(null); } catch (NoSuchFieldException | IllegalAccessException e) { throw new Error(e); } } static Unsafe getUnsafe() { return unsafe; } }
public class TestUnsafe { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafe.get(null); System.out.println(unsafe); // 1. 获取域的偏移地址 long idOffset = unsafe.objectFieldOffset(Teacher.class.getDeclaredField("id")); long nameOffset = unsafe.objectFieldOffset(Teacher.class.getDeclaredField("name")); Teacher t = new Teacher(); // 2. 执行 cas 操作 unsafe.compareAndSwapInt(t, idOffset, 0, 1); unsafe.compareAndSwapObject(t, nameOffset, null, "张三"); // 3. 验证 System.out.println(t); } } @Data class Teacher { volatile int id; volatile String name; }
Park & Unpark
基本使用
它们是 LockSupport 类中的方法
// 暂停当前线程 LockSupport.park(); // 恢复某个线程的运行 LockSupport.unpark(暂停线程对象)
先park 后 unpark
@Slf4j(topic = "c.TestParkUnpark") public class TestParkUnpark { public static void main(String[] args) { Thread t1 = new Thread(() -> { log.debug("start..."); sleep(1); log.debug("park..."); LockSupport.park(); log.debug("resume..."); }, "t1"); t1.start(); sleep(2); log.debug("unpark..."); LockSupport.unpark(t1); } } // 输出 // 13:34:19.631 c.TestParkUnpark [t1] - start... // 13:34:20.642 c.TestParkUnpark [t1] - park... // 13:34:21.635 c.TestParkUnpark [main] - unpark... // 13:34:21.635 c.TestParkUnpark [t1] - resume...
先unpark 后park
park失效
@Slf4j(topic = "c.TestParkUnpark") public class TestParkUnpark { public static void main(String[] args) { Thread t1 = new Thread(() -> { log.debug("start..."); sleep(2); log.debug("park..."); LockSupport.park(); log.debug("resume..."); }, "t1"); t1.start(); sleep(1); log.debug("unpark..."); LockSupport.unpark(t1); } } // 输出 //13:35:28.872 c.TestParkUnpark [t1] - start... //13:35:29.875 c.TestParkUnpark [main] - unpark... //13:35:30.883 c.TestParkUnpark [t1] - park... //13:35:30.883 c.TestParkUnpark [t1] - resume...
底层原理
底层是通过c代码实现
先park后unpark的情况
- 当前线程调用 Unsafe.park() 方法
- 检查 _counter ,本情况为 0,这时,获得 _mutex 互斥锁
- 线程进入 _cond 条件变量阻塞
- 设置 _counter = 0
如下图
- 调用 Unsafe.unpark(Thread_0) 方法,设置 _counter 为 1
- 唤醒 _cond 条件变量中的 Thread_0
- Thread_0 恢复运行
- 设置 _counter 为 0
先unpark后park的情况
- 调用 Unsafe.unpark(Thread_0) 方法,设置 _counter 为 1
- _cond 条件变量中无Thread_0,后续不执行
- 当前线程调用 Unsafe.park() 方法 检查 _counter ,本情况为 1,这时线程无需阻塞,继续运行
- 设置 _counter 为 0