《Java并发编程实战》4.高级主题

十三、显式锁

1)Lock与ReentrantLock

  • void lock(); 获取锁,未获取到则阻塞。

  • void lockInterruptibly() throws InterruptedException; 获取锁,未获取到则阻塞,阻塞可中断。

  • boolean tryLock(); 获取锁,返回是否获取到

  • boolean tryLock(long time, TimeUnit unit) throws InterruptedException; 获取锁,不能立即获取,则阻塞time时间,返回是否获取到。

  • void unlock(); 释放锁。

  • Condition newCondition(); 构建一个Condition条件,用于实现await、signal、signalAll 等待唤醒。

2)公平性

ReentrantLock支持公平锁与非公平锁,默认非公平。

  • 公平锁:获取锁时,如果锁被其他线程占用,则直接去排队挂起。

  • 非公平锁:获取锁时,如果锁被其他线程占用,先尝试获取一次,获取失败就去排队。

3)synchronize与ReentrantLock的选择

        在jdk1.8中,synchronize与ReentrantLock的性能差别不大,优先选择使用synchronize,当在一些功能上(锁超时、条件等待、可中断、公平性)不能满足时,再使用ReentrantLock。

        synchronize锁可通过jstack查看持有线程,也可以检索死锁,但ReentrantLock做不到。

 

十四、构建自定义同步工具

1)AQS

//AQS同步器维护的状态

private volatile int state;

//AQS中维护的等待链表,head头结点,tail尾结点

private transient volatile Node head;

private transient volatile Node tail;

//tryAcquire子类实现,判断当前state是否可做申请操作,返回true/false

//acquireQueued在tryAcquire返回false时执行,将线程封装成node放入队列并挂起线程,返回是否中断

public final void acquire(int arg) {

    if (!tryAcquire(arg) &&

        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))

        selfInterrupt();

}



//tryRelease子类实现,判断当前状态是否可做释放操作,返回true/false

//unparkSuccessor唤醒head节点之后第一个状态为-1的节点中的线程

public final boolean release(int arg) {

    if (tryRelease(arg)) {

        Node h = head;

        if (h != null && h.waitStatus != 0)

            unparkSuccessor(h);

        return true;

    }

    return false;

}

//tryAcquireShared子类实现,判断是否可做申请操作,返回int,小于0不可操作

//doAcquireShared将线程封装成node放入队列并挂起线程

public final void acquireShared(int arg) {

    if (tryAcquireShared(arg) < 0)

        doAcquireShared(arg);

}

//tryReleaseShared子类实现,判断是否可做释放操作,返回true/false

//doReleaseShared唤醒所有等待链表状态为-1节点的线程

public final boolean releaseShared(int arg) {

    if (tryReleaseShared(arg)) {

        doReleaseShared();

        return true;

    }

    return false;

}

//子类实现,在排他模式下,判断状态是否被占用

protected boolean isHeldExclusively();

2)并发包下的AQS

  • ReentrantLock

    • state记录了锁重入次数,并且还维护了owner线程

    • tryAcquire做state累加,state = 0未占用,state = N,被owner lock了N次,且做了owner的可重入判断。

    • tryRelease做了state减少,到0清理owner。

    • isHeldExclusively判断是不是当前线程。

  • Semaphore

    • state维护了许可证数。

    • tryAcquireShared做state减少,返回(当前-申请)。

    • tryReleaseShared做state增加。

  • CountDownLatch

    • state维护了需要count次数。

    • tryAcquireShared判断state是否为0,为0则返回1,否则返回-1,await调用acquireShared。

    • tryReleaseShared做state减少,每次减1,当减少到0是,返回true,否则返回false,countDown调用releaseShared。

  • ReentrantReadWriteLock

    • state维护一个32位的数,高16位维护读锁线程数,低16位维护锁重入次数。

    • tryAcquire 操作state低位增加,有读线程占着读锁||有其他线程占着写锁 返回false;其他情况增加state,且设置wtire线程。

    • tryRelease 操作state低位减少,低位减少到0返回true,且设置write线程为null。

    • tryAcquireShared 操作state高位增加,当前有其他线程的写锁返-1,否则高位加1返1。

    • tryReleaseShared 操作state高位减少,高位减1,减少整体为0,则返回true。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值