锁-独占锁、同步队列器
Lock接口
锁是用来控制多个线程访问共享资源的方式。一个锁可以防止多个线程同时访问共享资源(读写锁,允许多个线程并发的访问共享资源)
public static void main(String[] args) {
Lock lock = new ReentrantLock();
lock.lock();
try {
} finally {
lock.unlock();
}
}
这是锁的基本使用方式。
在finally块中释放锁,目的就是在获取锁后,能够最终释放锁。
不要将获取锁的过程写在try里面。如果获取锁发生异常抛出的时候,会导致锁无故释放。
队列同步器
AbstractQueuedSynchronizer(同步器),是用来构建锁或者其他同步组件的基础框架。
同步器的主要使用方式是继承,子类通过继承同步器并实现他的抽象方法,通过内置的FIFO队列来完成资源获取线程的排队工作。
同步器支持独占式的获取同步状态,也可以共享式的获取同步状态。
同步器的设计是基于模板方法模式的,也就是说,使用者必须继承同步器并重写指定的方法,随后将同步器组合在自定义同步组件的实现中,并调用同步器提供的模板方法,这些模板方法会调用使用者重写的方法。
重写同步器指定的方法时,需要使用这三个方法访问或者修改同步状态
getSate():获取当前同步状态
setState():设置当前同步状态
compareAndSetState(int expect,int update): 使用CAS设置当前状态,该方法能够保证状态设置的原子性
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
public class Mutex {
//静态内部类
private static class Sync extends AbstractQueuedSynchronizer {
//是否处于占用状态
@Override
protected boolean isHeldExclusively() {
return getState() == 1;
}
//当状态为1时,获取锁
@Override
protected boolean tryAcquire(int acquires) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
//释放锁,将状态设置为0
@Override
protected boolean tryRelease(int release) {
if (getState() == 0) {
throw new IllegalArgumentException();
}
setExclusiveOwnerThread(null);
setState(0);
return true;
}
//返回一个condition,每个condition都包含一个condition队列
Condition newCondition() {
return new ConditionObject();
}
}
//仅需要把操作代理到sync即可
private final Sync sync = new Sync();
public void lock() {
sync.acquire(1);
}
public boolean tryLock() {
return sync.tryAcquire(1);
}
public void unlock() {
sync.release(1);
}
public Condition newCondition() {
return sync.newCondition();
}
public boolean isLocked() {
return sync.isHeldExclusively();
}
public boolean hasQueueThreads() {
return sync.hasQueuedThreads();
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
}
上面可以看出:独占锁Mutex是一个自定义同步组件,他在同一时刻只允许一个线程占有锁。
在tryAcruire(int acruires)中,如果经过CAS设置成功(状态设置为1),则代表获取了通报状态。而在tryRelease(int release)中只是将同步状态重置为0.
同步器可以重写的方法
方法名称 | 描述 |
---|---|
protect boolean tryAcruire(int arg) | 独占式获取锁。实现前需要查询当前状态,并判断是否符合预期,然后经过CAS设置同步状态 |
protect boolean tryRelease(int arg) | 独占式释放锁。等待获取锁的线程将有机会获取锁 |
protect boolean tryAcruireShared(int arg) | 共享式获取锁,返回大于等于0的值,获取成功。反之,获取失败 |
protect boolean tryReleaseShared(int arg) | 共享式释放锁 |
protect boolean isHeldExclusively() | 查询当前线程是否被独占 |
同步器提供的模板方法??有疑问
void acquire(int arg) | 独占式获取锁,如果获取成功就返回,如果失败,将会进入同步队列中等待。该方法会调用重写的tryAcquire方法 |
---|---|
void acquireInterruptibly(int arg) | 与上面不同的是,这个可以响应中断,当前线程为获取到锁而进入到同步队列中,如果该线程被中断,或抛出异常 |
boolean tryAcquireNanos(int arg,long nanos) | 在void acquireInterruptibly(int arg)基础上加了超时限制。时间内获取成功就返回true,否则,返回false |
void acquireShared(int arg) | 共享式获取同步状态,如果为获取到,进入同步队列。同一时刻可以有多个线程获取到同步状态 |
boolean release(int release) | 独占式释放同步状态,释放后,会将同步队列的第一个节点包含的线程唤醒 |
boolean releaseShared(int release) | 共享式释放同步状态 |
Collection getQueueThreads() | 获取到同步队列上的线程集合 |
本文地址:https://blog.csdn.net/m0_50590769/article/details/109565526
上一篇: java File类的相关操作
下一篇: Vue 图片验证码生成