一、Lock接口:
在Lock接口出现之前,Java靠synchronized关键字实现锁的功能。但是synchronized关键字将锁的获取与释放固化了,显得并没有这么灵活。在jdk1.5以后,新增加了Lock接口。lock主要具备synchronized关键字锁不具备的以下同步特性:
(1).尝试非阻塞地获取锁:tryLock();
(2).能被中断地获取锁:lockInterruptibly();
(3).超时获取锁:tryLock(Long time,TimeUnit)
下面是Lock接口的API:
1)void lock():
获取锁,电泳该方法当前线程会获取锁,获得锁后,从该方法返回;
2)void lockInterruptibly():
可中断地获取锁,和lock()方法的不同之处在于该方法会响应中断,即在锁的获取中可以中断当前线程;
3)boolean tryLock():
尝试非阻塞的获取锁,调用该方法后立刻返回,如果能够获取则返回true,否则返回false;
4)boolean tryLock(long time,TimeUnit unit) throws InterruptedException:
超时获取锁,当前线程在以下三种情况下会返回:
①:当前线程在超时时间内获得了锁
②:当前线程在超时时间内被中断
③:超时时间结束,返回false
5)void unlock():
释放锁;
6)Condition newCondition():
获取等待通知组件,该组件和当前的锁绑定,当前线程只有获得了锁,才能调用该组件的wait()方法,而调用后,当前线程将释 放锁;
二、队列同步器(AbstactQueuedSynchronizer):——下面简称同步器。
1.定义:是用来构建锁或者其他同步组件的基础框架。使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。
2.同步器与锁的关系:同步器是实现锁的关键。锁是面向使用者的,它定义了使用者与锁交互的接口,隐藏了实现的细节;同步器面向的是锁的实现者,它简化了锁的实现方式,屏蔽了同步状态管理、线程排队、等待与唤醒等底层操作。
3.同步器可重写的方法:
protected boolean tryAcquire(int arg)——独占式获取同步状态;
protected boolean tryRelease(int arg)——独占式释放同步状态;
protected boolean tryAcquireShared(int arg)——共享式获取同步状态;
protected boolean tryReleaseShared(int arg)——共享式释放同步状态;
protected boolean isHeldExclusively()——表示同步器是否在独占模式下被线程占用。
同步器提供的模板方法基本上分为3类:
独占式获取与释放同步状态、共享式获取与释放同步状态、查询同步队列中的等待线程情况。
(独占锁就是在同意时刻只能有一个线程获取到锁,而其他获取锁的线程只能处于同步队列中等待)
4.自定义同步器——Mutex(独占锁)
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class Mutex implements Lock {
//静态内部类,自定义同步器
private static class Sync extends AbstractQueuedSynchronizer{
//是否处于占用状态
protected boolean isHeldExclusively(){
return getState() == 1;
}
//当状态为0时获取锁
protected boolean tryAcquire(int arg){
if(compareAndSetState(0,1)){
setExclusiveOwnerThread(Thread.currentThread()); //设置成功,则代表获取了同步状态。
return true;
}
return false;
}
//释放锁,将状态设置为0
protected boolean tryRelease(int releases){
if(getState()==0)
throw new IllegalMonitorStateException();
setExclusiveOwnerThread(null);
setState(0);
return true;
}
//返回一个Condition,每个condition都包含了一个condition队列
Condition newCondition(){
return new ConditionObject();
}
}
//仅仅需要将操作代理到Sync上即可
private final Sync sync = new Sync();
public boolean isLocked(){
return sync.isHeldExclusively(); //是否处于同步状态
}
@Override
public void lock() {
sync.acquire(1); //获取锁,将状态设置为1
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
return sync.tryAcquire(1);//尝试获取锁
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1,unit.toNanos(1000));
}
@Override
public void unlock() {
sync.release(1); //释放锁
}
@Override
public Condition newCondition() {
return sync.newCondition();
}
}
上述示例中,独占锁Mutex是一个自定义同步组件,它在同一时刻值允许一个线程占有锁。Mutex中定义了一个静态内部类,该内部类继承了同步器并实现了独占式获取和释放同步状态。