java AQS 框架一些理解
2017-04-29 11:49
218 查看
最近感觉基础有待加强,写点理论加深下自己的理解 ,第一次写博客希望大家给点建议,指点下
AQS的全称为(AbstractQueuedSynchronizer);
JAVA 主要实现类为 AbstractQueuedSynchronizer(结构如下)
AbstractQueuedSynchronizer主要结构入上图
1.AbstractQueuedSynchronizer 主要有一个标志锁状态的state 和指向队列头和尾的指针(主要成员变量为 state (标志锁的状态) head 指向等待获取锁队列的头 tail
指向获取队列的尾部)
2.AbstractQueuedSynchronizer 有两个内部类 Node(对等待获取锁线程的一个封装) 和 ConditionObject
下面结合ReentrantLock 源码分析下jdk怎么实现AQS(jdk1.7.0_67)
1.ReentrantLock 的构造函数两个ReentrantLock(),ReentrantLock(fair)
可以看到构造函数主要初始化sync 成员变量 ,下面以ReentrantLock()构造函数来说明;
初始化一个 sync = new NonfairSync(); NonfairSync继承Sync ,Sync
又继承AbstractQueuedSynchronizer
NonfairSync
主要实现 lock,tryAcquire;
2,我们看下ReentrantLock.lock
我们获取锁的入口函数
public
void lock() {
sync.lock();
}
调用的是
sync.lock();
sync的代码如下
final
void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
acquire 方法是在AbstractQueuedSynchronizer 实现的,代码如下
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
简单解释下上面代码compareAndSetState(0, 1) 利用CAS 原理修改AbstractQueuedSynchronizer 的成员变量state 如果修改成功则当前线程获取锁;
并把sync 锁所属线程设置成当前线程
如果不成功 则调用acquire(1);
我们在看下acquire(1) 的执行流程
if(!tryAcquire(1)&&acquireQueued(addWaiter(Node.EXCLUSIVE), 1))
selfInterrupt();
tryAcquire(1) 会调用 nonfairTryAcquire(1)
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
第一部分主要是当前线程继续尝试获取锁 第二个if是判断锁的持有者是不是当前线程
如果前两个if都没走则说明获取锁失败
继续走acquireQueued(addWaiter(Node.EXCLUSIVE),
addWaiter方法是将没获取锁的线程组装成Node 对象 放入获取锁线程队列中(代码如下)
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
加入后我们看下acquireQueued()方法,
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; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
这是个死循环 如果p == head && tryAcquire(arg) 不满足则会调用parkAndCheckInterrupt
阻塞线程
最终调用的是unsafe.park(false,
0L),阻塞线程这是个native方法这里不解释了
3.最后我们看下unlock函数怎样释放锁的
public
void unlock() {
sync.release(1);
}
public
final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
private
void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
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;
}
if (s != null)
LockSupport.unpark(s.thread);
}
主要是修改syn的状态变量 队列的移除,唤醒其他线程
AQS的全称为(AbstractQueuedSynchronizer);
JAVA 主要实现类为 AbstractQueuedSynchronizer(结构如下)
AbstractQueuedSynchronizer主要结构入上图
1.AbstractQueuedSynchronizer 主要有一个标志锁状态的state 和指向队列头和尾的指针(主要成员变量为 state (标志锁的状态) head 指向等待获取锁队列的头 tail
指向获取队列的尾部)
2.AbstractQueuedSynchronizer 有两个内部类 Node(对等待获取锁线程的一个封装) 和 ConditionObject
下面结合ReentrantLock 源码分析下jdk怎么实现AQS(jdk1.7.0_67)
1.ReentrantLock 的构造函数两个ReentrantLock(),ReentrantLock(fair)
可以看到构造函数主要初始化sync 成员变量 ,下面以ReentrantLock()构造函数来说明;
初始化一个 sync = new NonfairSync(); NonfairSync继承Sync ,Sync
又继承AbstractQueuedSynchronizer
NonfairSync
主要实现 lock,tryAcquire;
2,我们看下ReentrantLock.lock
我们获取锁的入口函数
public
void lock() {
sync.lock();
}
调用的是
sync.lock();
sync的代码如下
final
void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
acquire 方法是在AbstractQueuedSynchronizer 实现的,代码如下
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
简单解释下上面代码compareAndSetState(0, 1) 利用CAS 原理修改AbstractQueuedSynchronizer 的成员变量state 如果修改成功则当前线程获取锁;
并把sync 锁所属线程设置成当前线程
如果不成功 则调用acquire(1);
我们在看下acquire(1) 的执行流程
if(!tryAcquire(1)&&acquireQueued(addWaiter(Node.EXCLUSIVE), 1))
selfInterrupt();
tryAcquire(1) 会调用 nonfairTryAcquire(1)
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
第一部分主要是当前线程继续尝试获取锁 第二个if是判断锁的持有者是不是当前线程
如果前两个if都没走则说明获取锁失败
继续走acquireQueued(addWaiter(Node.EXCLUSIVE),
addWaiter方法是将没获取锁的线程组装成Node 对象 放入获取锁线程队列中(代码如下)
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
加入后我们看下acquireQueued()方法,
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; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
这是个死循环 如果p == head && tryAcquire(arg) 不满足则会调用parkAndCheckInterrupt
阻塞线程
最终调用的是unsafe.park(false,
0L),阻塞线程这是个native方法这里不解释了
3.最后我们看下unlock函数怎样释放锁的
public
void unlock() {
sync.release(1);
}
public
final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
private
void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
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;
}
if (s != null)
LockSupport.unpark(s.thread);
}
主要是修改syn的状态变量 队列的移除,唤醒其他线程
相关文章推荐
- 接触Java项目一周后对一些基本框架的理解
- java2集合框架的一些个人分析和理解
- Java学习过程应该深入理解的一些重点
- JAVA编码问题的一些理解
- 关于java反射的一些理解
- EXT 如何与一些java 框架集成(关于Ext校验)
- java String 类的一些理解 关于==、equals、null
- JAVA编码问题的一些理解
- eclipse编译器编码与jsp java 等文件编码一些自己的理解
- Java学习过程应该深入理解的一些重点
- 对Java同步一些理解
- springside3框架中prepareModel的一些理解总结
- 【转载】Java学习过程应该深入理解的一些重点
- JAVA基础知识: 对synchronized(this)的一些理解
- 对Java同步一些理解
- JAVA编码问题的一些理解
- Java学习过程应该深入理解的一些重点
- Java学习过程中应该理解的一些重点内容
- Java学习过程中应该深入理解的一些重点
- 框架和架构的一些的理解