死磕多线程(6)-lock体系简介

Lock体系:

JDK1.5之后,增加java.util.concurrent.locks提供了与内建锁完全不同的实现多线程共享资源访问机制。失去了内建锁隐式的加锁与解锁的过程,增加了 可中断的获取锁 以及 超时获取锁 以及 共享锁 等内建锁不具备的特性。
下面将对lock体系进行系统的介绍。

一、lock锁(接口)的标准使用形式

Lock lock = new ReentrantLock();
try{
    lock.lock();
    //同步块
}finally{
    lock.unlock();
}

二、lock接口API

  • void lock();-----获取锁
  • void lockInterruptibly() throws InterruptedException----获取锁的过程能够响应中断(lock独有)
  • Boolean tryLock()----非阻塞式响应中断,能立即返回,获取锁返回true反之为false
  • boolean tryLock(long time,TimeUnit unit)----增加了超时等待机制,规定时间内未获取到锁,线程直接返回(lock独有)
  • void unlock()----解锁

三、AbstractQueuedSynchronizer(AQS,同步器),lock体系最核心的存在
同步器是用来构建锁与其他同步组件的基础框架。它的实现主要是依赖一个int成员变量来表示同步状态以及通过一个FIFO 队列构成同步队列
要使用AQS,推荐使用静态内部类继承AQS,重写AQS中的protected用来改变同步状态的方法,其他方法主要是实现排队与阻塞机制。
eg:AQS中需要重写的方法tryAcquire:

protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}

ReentrantLock中NonfairSync(继承AQS)会重写该方法为:

protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}

在重写AQS的方法时,使用AQS提供的getState(),setState(),compareAndSetState()方法可以进行同步状态的修改。
lock面向使用者定义了使用者与锁交互的接口,隐藏了实现细节;
AQS面向锁的实现者,简化了锁的实现方式,屏蔽同步状态的管理,线程排队,线程等待与唤醒等底层操作。

四、AQS提供的模板方法
AQS的核心包括了:同步队列,独占式锁的获取和释放,共享锁的获取和释放以及可中断锁,超时等待锁获取这些特性的实现,而这些实际上则是AQS提供出来的模板方法:
独占锁:
1.void acquire(int arg):独占式获取同步状态,如果获取失败则将当前线程插入同步队列进行等待2.void acquireInterruptibly(int arg):在1的基础上增加响应中断
3.Boolean tryAcquireNanos(int arg,long nanosTimeOut):在2的基础上增加超时等待,在规定时间内未获取到同步状态返回false
4.boolean tryAcquire(int arg):获取状态成功返回true,否则返回false
5.boolean ralease(int arg):释放同步状态,该方法会唤醒在同步队列中的下个节点。

共享锁:
1.void acquireShared(int arg) : 共享式获取同步状态,与独占锁的区别在于同一时刻有多个线程获取同步状态。
2.void acquireSharedInterruptibly(int arg) : 增加了响应中断的功能
3. boolean tryAcquireSharedNanos(int arg,lone nanosTimeout) : 在2的基础上增加了超时等待功能
4. boolean releaseShared(int arg) : 共享锁释放同步状态。

五、AQS中的同步队列
AQS中的同步队列是一个带有头尾节点的双向链表,节点的组成为Node prev,Node next,Thread thread,将线程封装为Node节点后,进行排队与入队与出队处理。
在这里插入图片描述
单个节点的入队和出队对应着锁的获取和释放两个操作:
获取锁失败进行入队操作,获取锁成功进行出队操作。

六、同步队列
同步队列在AQS内部有一个静态内部类Node,这是同步队列中每个具体的节点。
节点有如下属性:
int waitStatus:节点状态
Node prev:同步队列中前驱节点
Node next:同步队列中后继节点
Thread thread:当前节点包装的线程对象
Node nextWaiter:等待队列中下一个节点

节点状态值如下:
int INITIAL = 0; // 初始状态
int CANCELLED = 1;// 当前节点从同步队列中取消
int SIGNAL = -1; // 后继节点处于阻塞(WAIT)状态。如果当前节点释放同步状态会通知后继节点,使后继节点继续运行。
int CONDITION = -2; // 节点处于等待队列中。当其他线程对Condition调用signal()方法后,该节点会从等待队列移到同步队列中
int PROPAGATE = -3; // 共享式同步状态会无条件的传播

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值