利用队列同步器构建独占锁

队列同步器是构建锁和其他同步组件的基础框架,他使用一个int型成员变量表示同步状态,通过内置FIFO队列来完成资源获取线程的排队工作。
同步器AbstractQueuedSynchonizer是一个抽象类,他的使用方式是继承,子类通过继承同步器并实现他的抽象方法来管理同步状态。
同步器中可以被重写的方法有:
(1)protected boolean tryAcquire(int arg)//独占式获取同步状态,实现该方法要查询当前状态并判断同步状态是否符合预期,然后进行CAS设置同步状态
(2)protected boolean tryRelease(int arg)//独占式释放同步状态,等待获取同步状态的线程有机会获取同步状态。
(3)protected int tryAcquireShared(int arg)//共享式获取同步状态,如果返回大于等于0的值表示获取成功;反之表获取失败
(4)protected boolean tryReleaseShare(int arg)//共享式释放同步状态
(5)protected boolean isHeldExclusively()//当前同步器是否在独占模式下被线程占用,一般表是否被当前线程占用
重写队列同步器的指定方法时需要使用如下三个方法来获取和修改同步状态
(1)getState():获取当前同步状态
(2)setState(int newState):设置当前同步状态
(3)compareAndSetState(int expect,int update):如果当前状态为expect,则将当前状态更新为update,并返回true;否则直接返回false;使用CAS设置当前状态,保证状态设置的原子性 (后面会专门花时间讲CAS)

package 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;//获取当前状态,也就是获取队列同步器表示同步状态的int型变量的值,为1表示被占用,否则未被占用。
        }
        public boolean tryAcquire(int acquires)
        {
            if(compareAndSetState(0,1))
            {//当状态为0获取锁
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;//当前状态不为0,即被占用,则无法再获取锁,这时直接返回false,体现了独占性
        }
        protected boolean tryRelease(int releases)
        {
            if(getState()==0) 
                throw new IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }
        Condition newCondition()
        {
            return new ConditionObject();
        }
    }
    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 hasQueuedThreads()
    {
        return sync.hasQueuedThreads();
    }
    public void lockInterruptibly() throws InterruptedException
    {
        sync.acquireInterruptibly(1);
    }
    public boolean tryLock(long timeout,TimeUnit unit) throws InterruptedException
    {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }  
}

用户使用Mutex时并不会直接和内部的同步器直接打交道,而是调用Mutex提供的方法,在Mutex中,以lock方法为例,当前线程调用该方法获取同步状态失败后会被加入到同步队列中等待。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值