美文网首页
Java 显示锁和AQS 一

Java 显示锁和AQS 一

作者: 攻城狮托马斯 | 来源:发表于2020-05-14 13:46 被阅读0次

内置锁和显示锁


显示锁接口: Lock(); 内置锁: Synchronize();

显示锁的不同


lockInterruptibly() 在拿锁途中暂停

tryLock() 尝试去拿锁, 超时获取锁(在一定时间内如果没有获得锁, 那就放弃)

除非需要用到以上两种方式, 否则还是用synchronize.

因为synchronize消耗会比Lock消耗的少, synchronize是一个语言的特性, 而Lock需要新建对象消耗资源

使用最多的显示锁: ReentrantLock(), ReadLock(), WriteLock() in ReentrantReadWriteLock

实用的范式


public void test() {

lock.lock()

try{ 

    age++;

} finally {

lock.unlock()//在finally中一定释放

}

}

ReentrantLock()  可重入锁


可二次取锁, 不会出现自己把自己锁死的情况, 比如说在recursion中反复取锁.

非公平与公平锁


为什么要用非公平锁(不按照排队顺序拿锁)

如果三个线程在等锁, 唤醒第一个线程A需要5000-10000的上下文切换耗能, 在唤醒第一个线程的途中,恰好有一个线程K取锁,那么锁会先给这个线程K, 说不定等K完成了任务,A正好苏醒并拿到了锁.

Synchronize是一个非公平锁. 而ReentrantLock(Boolean isFair) 可以根据传入的数据initialize这个锁是否是公平或者不公平的

读写锁(非独占锁) Interface ReadWriteLock()


在读多写少的时候, 使用读写分离.

Synchronize是独占锁, 而ReadWriteLock()中,read是非独占锁(排斥写锁), 只有write是独占锁(排斥其他的写锁和读锁)

Condition接口(对应Synchronize中的wait()和notify())


其中的方法有: await(), signal(), signalAll(), 和之前synchronize是一模一样的.

比如, 在synchronize的wait()中, 首先会锁住对象, 然后当while(条件) object.wait(), 在lock中是一模一样的。signal()和signalAll()也是一模一样,只有在最后一行的时候才会signal(), 然后在finally中手动释放锁.(之所以放在最后一行是因为如果还没做完事情就把别人唤醒, 让他人等待, 是一件很不效率的事情)

LockSupport 工具类


提供了一组静态方法, park(Object) 阻塞当前线程, unpark(Thread)唤起当前线程. 

CLH队列锁


内部实现锁基本都基于CLH实现.  CLH是一个DoublyLinkedList,每一个Node有一个prev的指针, 有一个boolean来判断是否被lock住。且每一个pred都会进行自旋来查看前一个Node是否释放锁.(自旋指的不让线程执行其他任务而等待锁,因为等待时间小于切换任务的overhead, 这里用自旋合适吗?)

如上图, 右侧,当NodeA的prev是false, 也就是说前一个线程释放锁了之后, NodeA就获得了锁, locked改为true, B就一直等锁.

AQS


AQS在所有的锁中都有实现, reentryLock(), semaphore()

比如说:

public class SelfLock implements Lock{

private static class Sync extends AbstractQueueSynchronizer{}}

本质上, AQS就是一个CLH锁, 

而AQS的同步性是通过CAS来实现的.

AQS需要实现的Function


比如说:  acquire()和release()

acquire() ——> tryacquire() ——> compareAndSetState(expect: 0, update: 1);

如果成功了, 就setExclusiveOwnerThread(Thread.currentThread());

release()——> tryrelease() ——>setState(0);

如果成功了, 就setState(0);

AQS中的Node


在AQS中, 有Node的数据结构, 数据结构中的解释, 包括:

· Thread: 当前线程

· Share:分享模式等待锁, Exclusive: 独享锁

· WaitStatus: 1.Cancel:取消获取锁  2.Signal: 当前线程已准备好 3.Condition:等待某个条件被满足

4.Propagate: 当线程属于共享模式的时候, 把当前正在等待锁的线程传播下去。

· nextWaiter(): 等待condition满足的节点

·prev, next

相关文章

网友评论

      本文标题:Java 显示锁和AQS 一

      本文链接:https://www.haomeiwen.com/subject/cdhtohtx.html