ReentrantLock是一个互斥的同步器,其实现了接口Lock,里面的功能函数主要有:
1. lock() — 阻塞模式获取资源
2. lockInterruptibly() — 可中断模式获取资源
3. tryLock() — 尝试获取资源
4. tryLock(time) — 在一段时间内尝试获取资源
5. unlock() — 释放资源
ReentrantLock实现Lock有两种模式即公平模式和不公平模式
Concurrent包下的同步器都是基于AQS框架,在ReentrantLock里面会看到这样三个类
———————————————————————–
static abstract class Sync extends AbstractQueuedSynchronizer {
abstract void lock();
final boolean nonfairTryAcquire(int acquires) { … }
protected final boolean tryRelease(int releases) { … }
}
———————————————————————–
final static class NonfairSync extends Sync {
protected final boolean tryAcquire(int acquires) { … }
final void lock() { … }
}
———————————————————————–
final static class FairSync extends Sync {
final void lock() { … }
protected final boolean tryAcquire(int acquires) { … }
}
———————————————————————–
再回归到ReentrantLock对Lock的实现上
0. ReentrantLock实例化
ReentrantLock有个属性sync,实际上对Lock接口的实现都是包装了一下这个sync的实现
如果是公平模式则创建一个FairSync对象,否则创建一个NonfairSync对象,默认是不公平模式
1. lock() 调用sync.lock()
公平模式下:直接走AQS的acquire函数,此函数的逻辑走一次tryAcquire,如果成功
线程拜托同步器的控制,否则加入NODE链表,进入acquireQueued的tryAcquire,休眠,被唤醒的轮回
不公平模式下和公平模式下逻辑大体上是一样的,不同点有两个:
a. 在执行tryAcquire之前的操作,不公平模式会直接compareAndSetState(0, 1)原子性的设置AQS的资源
0表示目前没有线程占据资源,则直接抢占资源,不管AQS的NODE链表的FIFO原则
b. tryAcquire的原理不一样,不公平模式的tryAcquire只看compareAndSetState(0, 1)能否成功
而公平模式还会加一个条件就是此线程对于的NODE是不是NODE链表的第一个
c. 由于tryAcquire的实现不一样,而公平模式和不公平模式在lock期间走的逻辑是一样的(AQS的acquireQueued的逻辑)
d. 对于一个线程在获取到资源后再调用lock会导致AQS的资源做累加操作,同理线程要彻底的释放资源就必须同样
次数的调用unlock来做对应的累减操作,因为对应ReentrantLock来说tryAcquire成功一个必须的条件就是compareAndSetState(0, 1)
e. 由于acquireQueued过程中屏蔽了线程中断,只是在线程拜托同步器控制后,如果记录线程在此期间被中断过则标记线程的
中断状态
2. lockInterruptibly() 调用sync.acquireInterruptibly(1),上一篇文章讲过AQS的核心函数,这个过程和acquireQueued
是一样的,只不过在阻塞期间如果被标记中断则线程在park期间被唤醒,然后直接退出那个轮回,抛出中断异常
由于公平模式和不公平模式下对tryAcquire的实现不一样导致lockInterruptibly逻辑也是不一样
3. tryLock() 函数只是尝试性的去获取一下锁,跟tryAcquire一样,这两种模式下走的代码一样都是公平模式下的代码
4. tryLock(time) 调用sync.tryAcquireNanos(time),上一篇文章讲过AQS的核心函数,这个过程和acquireQueued一样,
a. 在阻塞前会先计算阻塞的时间,进入休眠
b. 如果被中断则会判断时间是否到了
1. 如果没到则且被其他线程设置了中断标志,退出那个轮回,抛出中断异常,如果没有被设置中断标记则是前一个线程
释放了资源再唤醒了它,其继续走那个轮回,轮回中,如果tryAcquire成功则摆脱了同步器的控制,否则回到a
2. 如果时间到了则退出轮回,获取资源失败
5. unlock() 调用sync.release(1),上一篇文章讲过AQS的核心函数,release函数会调用Sync实现的tryRelease函数来判断
释放资源是否成功,即Sync.tryRelease函数,其逻辑过程是
a. 首先判断目前占据资源的线程是不是调用者,如果不是会抛出异常IllegalMonitorStateException
b. 如果是则进行AQS资源的减1逻辑,如果再减1后AQS资源变成0则表示调用线程测得放弃了此锁,返回给release的值的TRUE,
release会唤醒下一个线程
———————————————————————–
整体来看ReentrantLock互斥锁的实现大致是
1. 自己实现AQS的tryAcquire和tryRelease逻辑,tryAcquire表示尝试去获取锁,tryRelease表示尝试去释放锁
2. ReentrantLock对lock(),trylock(),trylock(time),unlock()的实现都是使用AQS的框架,然后AQS的框架又返回调用
ReentrantLock实现的tryAcquire和tryRelease来对线程是否获取锁和释放锁成功做出依据判断
[来源:http://www.cnblogs.com/mandela/archive/2011/04/08/2009810.html]
分类目录
- arch/management (17)
- computer (38)
- java/j2ee (304)
- lnmpa (237)
- mac/iphone/ipad/android (11)
- mysql/oracle/postgresql (126)
- os/software (74)
- other (518)
- python (6)
- redis/memcached/mongo (31)
- sitebuild (143)
随便看看
标签云
程序员 创业 人生箴言 eclipse 快捷键 术语 索引 unix命令 vim wordpress java学习笔记 环境变量 oracle内置函数 index 人生 数据类型 nohup tuxedo mysql学习笔记 MS-DOS命令 servlet spring 职场进阶 职业进阶 服务器选购 服务器选型 apache JPA MongoDB 注解 tomcat 子女教育 jquery maven JVM aix命令 网络营销 java异常 seo 人生规划 关键字 css 网络推广 struts 系统优化 成长 frame iframe bluehost jdbc select 我的信仰 oracle函数 cookie HashMap 站长工具 乱码 ArrayList secureCRT jsp session tail find halt 事务 oracle单记录函数 算法 URL window table javascript操作表单元素 String 字符串处理 健康 http 域名 情感 more google A记录 域名解析 netstat 弹出对话框 弹出窗口 框架集 框架 excel 字符串 javascript函数 showModalDialog nginx number 数组 sql frameset 开源程序 java数组 软件 oracle服务友情链接
收藏链接