ReentrantLock
2021-01-22 11:42:52 0 举报
ReentrantLock
作者其他创作
大纲/内容
NonfairSync
unlock()
return t;
setExclusiveOwnerThread(Thread.currentThread());
return true;
this.items = new Object[capacity]; // 创建制定容量的队列 lock = new ReentrantLock(fair); // 构造互斥锁 notEmpty = lock.newCondition(); // 创建条件等待队列,当队列非空触发条件 notFull = lock.newCondition(); // 创建条件等待队列,当队列不满的时候出发条件
如果方法返回true,代表可以对节点节点阻塞
cas操作设置当前节点为tail节点
当前线程获取锁失败,判断是否可以被阻塞
唤醒阻塞线程
free = true;
cancelAcquire(node);
for (;;)死循环,对阻塞的node节点进行park操作
t == null
node.prev = pred;
tryRelease(arg)
setHead(node);
false,判断当前线程是否为持有锁的线程
return false;
hasQueuedPredecessors()
tail = head;
使用cas操作设置队尾
LockSupport.park(this);
判断节点状态是否为-1,如果节点状态为0,使用cas将节点状态设置为-1,如果节点状态大于0,则进行忽略,不处理节点的状态都是相对于当前的prev节点而言
acquire(1);
如果尾节点为空初始化节点,并设置为头节点
AbstractOwnableSynchronizer
ReentrantLock
获取信号量并减1
final Node p = node.predecessor();
true
p.next = null;
设置失败,同步状态获取锁
addWaiter(Node.EXCLUSIVE)
setState(c);
enq(node);
true,前当前节点的前驱节点指向tail
创建当前线程节点,设置为独占模式
unparkSuccessor(h);
公平锁,采用了模板模式
if (tryRelease(arg))
c == 0
return free;
Node s = node.next; if (s == null || s.waitStatus > 0) { s = null; for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; }
return node;
selfInterrupt()
阻塞当前线程
sync.release(1);
尝试获取锁状态
false
执行完unpark以后被唤醒的线程会继续执行该处,去获取锁,则调出循环继续执行业务代码
将当前持有锁的线程设置为当前线程
Sync
阻塞唤醒
唤醒当前节点
非公平锁实现
采用尾插发将当前节点插入到队列
将head、tail指向当前空节点
当前节点指向,队列的tail节点
剔除掉当前节点之前的状态为CANCELLED的节点,并设置当前节点状态为CANCELLED,如果当前节点为tail,直接剔除掉当前节点。如果当前的node为prev则直接唤醒当前节点
t.next = node;
return false;
返回node节点
false,将当前互斥变量加 + 1
for (;;) 循环处理节点,保证阻塞节点能够进入队列
如果当前节点前驱节点为头节点,尝试获取锁
parkAndCheckInterrupt()
是
将头节点的下个节点设置为空
tail节点为空,对节点入队列
Thread.currentThread().interrupt();
将头节点状态设置为0
Node t = tail;
pred != null
true,判断头节点不等于空且是可唤醒状态
LockSupport.unpark(s.thread);
返回线程是否被阻塞,清除线程阻塞标记
公平锁:存在锁竞争以后线程会被放入到阻塞队列非公平锁:存在所竞争以后,线程直接对锁进行竞争
node.prev = t;
AbstractQueuedSynchronizer
int c = getState();
if (h != null && h.waitStatus != 0)
NonfairSync.lock()
标记当前线程为中断,用于外部代码进行判断
current == getExclusiveOwnerThread()
lock()
获取锁状态
p == head && tryAcquire(arg)
int nextc = c + acquires;
failed == true如果该线程是被中断唤醒,设置节点状态为waitStatus
找到当前线程的前驱节点
setExclusiveOwnerThread(current);
其他情况,为该线程没有获取到锁,返回false
内部类
ArrayBlockingQueue
如果线程没有获取到锁,将线程添加到阻塞队列
构造方法
int c = getState() - releases;
setState(nextc);
如果当前线程持有锁,互斥量 + 1
当前线程获取锁成功,将当前节点设置为头节点清空当前节点thread指向、清空prev指针指向
设置互斥变量
将最后节点的指针指向当前node
setExclusiveOwnerThread(null);
private transient Thread exclusiveOwnerThread; 属性,用来存储当前持有锁的线程
FairSync
判断当前队列中是否存在阻塞的线程,或者头节点的下一个线程是否为当前线程
定义了Node类,Node类属性:Node prev; 指向前驱指针。Node next;指向后继指针。通过这两个指针形成了双向链表。volatile Thread thread;记录当前被阻塞的线程private transient volatile Node head; 阻塞队列中的头指针private transient volatile Node tail;阻塞队列中的尾指针private volatile int state;互斥变量
设置state状态后将当前线程设置当前线程
Node pred = tail;判断尾节点是否为null
sync.lock();
判断当前前驱节点的状态是否为可唤醒状态
设置state的值
从tail开始遍历,找到队列中第一个状态有效的节点
return Thread.interrupted();
队列尾节点指向当前节点
compareAndSetHead(new Node())
将当前占有锁的线程清空
tryAcquire(arg)
判断对线程是否阻塞
公平锁实现类
pred.next = node;
0 条评论
下一页