您的位置:首页 > 编程语言 > Java开发

java锁(1)之ReentrantLock

2016-01-24 11:00 405 查看

ReentrantLock

1.        特点:

1)        ReentrantLock提供了两种锁:公平锁和非公平锁。

2)        ReentrantLock是可重入的:一个线程可以多次调用lock成功,但要求调用了多少次lock,就需要对应调用多少次unlock

3)        ReentrantLock除了实现Lock接口外,还提供了一些辅助的方法,如:isLocked和getQueueLength等,这些方法对检测和监视可能很有用。

非公平锁

1.        获取一个非公平锁:



2.        实现:

1)        获取锁资源:通过ReentLock的lock来申请锁。

使用的AQS实现类NofairSync(非公平同步)的lock方法。



在新线程获取锁是没有加任何限制,这里体现了非公平性,即新的和旧的一起竞争。

a)        通过CAS操作,比较并设置锁的状态,来改变锁的状态。即尝试去获取锁。0与当前所得状态比较,若相等需改(获取)成功。

b)        若成功,修改当前锁的owner为自己。

c)        若不成功,调用acquire()方法。在acquire中干了如下几件事



Ø  再次尝试获取锁,若成功则返回。

u  获取当前锁的状态

u  若空闲,则修改锁的状态、是指锁的owner为自己,返回True

u  若不空闲,则判断锁的持有者是否是自己

n  若是,锁状态+1,返回True

u  返回false

Ø  再次获取锁失败后,将本线程通过addWaiter()方法将自己加入等待队列中,返回在等待队列中表示本线程的结点。

Ø  使线程进入阻塞睡眠。

2)        释放锁资源:通过ReentLock的unlock来释放锁

使用AQS的release方法。



Ø  release中线程使用tryRelease释放锁,释放锁成功后将进入唤醒等待线程;

Ø  如果队列不为空,并且head的waitStatus不为0,即存在后续节点的线程等待被唤醒,则调用unparkSuccessor唤醒后续节点的线程。

Ø  否则返回false

a)        tryRelease(int arg):

Ø  tryRelease中获取AQS的状态,并减去releases(释放锁),得到c;

Ø  如果执行的线程不是锁的owner,则抛出异常

Ø  若是,则判断c(表示剩余需要被释放的次数)

n  如果c为0,则表示锁已经被释放,将锁的owner设置为空,

n  设置AQS的state状态标志位为c;(此时c为当先还需unlock的次数,可能是0,也可能不是0)

n  返回锁是否都释放了。

b)        若tryRelease返回true表示锁锁了等同的unlock操作。即锁释放。

Ø  使用unparkSuccessor唤醒等待队列中对头的阻塞线程。

Ø  若后续中还存在可被唤醒的线程,则继续唤醒。

公平锁

1.        公平锁和非公平锁区别:

1)        非公平锁是新到的线程和等待队列中的线程一起竞争锁;

2)        公平锁则始终保证等待最长的线程获取锁。



Ø  公平锁和非公平锁的区别就在于多了hasQueuedPredecessors判断

Ø  hasQueuedPredecessors判断是否有等待线程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息