把共享数据的可见范围限制在同一个线程之内,这样,无须同步也能保证线程之间不出现数据争用的问题
使用:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | public class ThreadLocalExample {public static void main(String[] args) {
 ThreadLocal threadLocal = new ThreadLocal();
 Thread thread1 = new Thread(() -> {
 threadLocal.set(1);
 try {
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 System.out.println(threadLocal.get());
 threadLocal.remove();
 });
 Thread thread2 = new Thread(() -> {
 threadLocal.set(2);
 threadLocal.remove();
 });
 thread1.start();
 thread2.start();
 }
 }
 
 
 | 
原理
![]()
ThreadLocal#set:把值存到当前线程的 ThreadLocalMap 中
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 
 | public void set(T value) {Thread t = Thread.currentThread();
 ThreadLocalMap map = getMap(t);
 if (map != null) {
 map.set(this, value);
 } else {
 createMap(t, value);
 }
 }
 
 ThreadLocalMap getMap(Thread t) {
 
 return t.threadLocals;
 }
 
 static class ThreadLocalMap {
 static class Entry extends WeakReference<ThreadLocal<?>> {
 
 Object value;
 
 Entry(ThreadLocal<?> k, Object v) {
 super(k);
 value = v;
 }
 }
 ...
 }
 
 | 
内存泄露
ThreadLocal 对象 new 后有强引用,而当前线程中的 ThreadLocalMap 对象的键也有 ThreadLocal 对象的弱引用,所以当 ThreadLocal 对象失去强引用时 ThreadLocalMap 中对应的键也会变为 null,防止了内存泄露。
虽然 ThreadLocalMap 的键为 null 了,但是其 value 值还存在所以依然会有内存泄露,所以需要执行 ThreadLocal#remove 方法。
Java 技术之 AQS 详解
内部维护一个 state 和一个双向线程链表
![]()
![]()
- ReentrantLock#lock 
- AbstractQueuedSynchronizer#compareAndSetState:CAS 把 state 从 0 变为 1,若成功则代表拿到锁  
- AbstractOwnableSynchronizer#setExclusiveOwnerThread:若抢到锁,则设置当前线程为独占线程  
- AbstractQueuedSynchronizer#acquire  | 12
 3
 4
 5
 
 | public final void acquire(int arg) {if (!tryAcquire(arg) &&
 acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
 selfInterrupt();
 }
 
 |  
 
- ReentrantLock.NonfairSync#tryAcquire
 1. ReentrantLock.Sync#nonfairTryAcquire:
 - 
- state 为 0,则继续调用 compareAndSetState 抢锁(尝试把 state 变为 1,成功则接着调用 setExclusiveOwnerThread)
- state 为 > 0,且当前线程是独占访问的那个线程(说明锁重入),则 state++(此时 state 代表重入线程数)
- 否则 TryAcquire 失败
 
-  TryAcquire 失败则调用 AbstractQueuedSynchronizer#addWaiter:使用 CAS 加入链表队列 
 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 
 | private Node addWaiter(Node mode) {
 Node node = new Node(Thread.currentThread(), mode);
 
 Node pred = tail;
 if (pred != null) {
 
 
 node.prev = pred;
 if (compareAndSetTail(pred, node)) {
 pred.next = node;
 return node;
 }
 }
 enq(node);
 return node;
 }
 private Node enq(final Node node) {
 for (;;) {
 Node t = tail;
 if (t == null) {
 if (compareAndSetHead(new Node()))
 tail = head;
 } else {
 node.prev = t;
 if (compareAndSetTail(t, node)) {
 t.next = node;
 return t;
 }
 }
 }
 }
 
 | 
jdk 9 使用 VarHandler.set(this, pred) 代替 node.prev = pred;,其调用 native 实现(相当于直接操纵二进制码),效率比反射高
VarHandler 指向一个变量  
     1. AbstractQueuedSynchronizer#acquireQueued:加入队列后不断监听前一个节点,若前节点为头结点(已拿到锁),则试图去抢锁,成功则返回 false(不中断)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | final boolean acquireQueued(final Node node, int arg) {boolean failed = true;
 try {
 boolean interrupted = false;
 for (;;) {
 final Node p = node.predecessor();
 if (p == head && tryAcquire(arg)) {
 setHead(node);
 p.next = null;
 failed = false;
 return interrupted;
 }
 if (shouldParkAfterFailedAcquire(p, node) &&
 parkAndCheckInterrupt())
 interrupted = true;
 }
 } finally {
 if (failed)
 cancelAcquire(node);
 }
 }
 
 | 
参考