• concurrent(三)互斥锁ReentrantLock & 源码分析


    参考文档:
    Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock:http://www.cnblogs.com/skywang12345/p/3496101.html

    ReentrantLock介绍

    ReentrantLock是一个可重入的互斥锁,又被称为“独占锁”
    ReentrantLock分为“公平锁”和“非公平锁”。它们的区别体现在获取锁的机制上是否公平。ReentraantLock是通过一个FIFO的等待队列来管理获取该锁所有线程的
    公平锁:线程依次排队获取锁
    非公平锁:在锁是可获取状态时,不管自己是不是在队列的开头都会获取锁

    ReentrantLock函数列表

    // 创建一个 ReentrantLock ,默认是“非公平锁”。
    ReentrantLock()
    // 创建策略是fair的 ReentrantLock。fair为true表示是公平锁,fair为false表示是非公平锁。
    ReentrantLock(boolean fair)
    
    // 查询当前线程保持此锁的次数。
    int getHoldCount()
    // 返回目前拥有此锁的线程,如果此锁不被任何线程拥有,则返回 null。
    protected Thread getOwner()
    // 返回一个 collection,它包含可能正等待获取此锁的线程。
    protected Collection<Thread> getQueuedThreads()
    // 返回正等待获取此锁的线程估计数。
    int getQueueLength()
    // 返回一个 collection,它包含可能正在等待与此锁相关给定条件的那些线程。
    protected Collection<Thread> getWaitingThreads(Condition condition)
    // 返回等待与此锁相关的给定条件的线程估计数。
    int getWaitQueueLength(Condition condition)
    // 查询给定线程是否正在等待获取此锁。
    boolean hasQueuedThread(Thread thread)
    // 查询是否有些线程正在等待获取此锁。
    boolean hasQueuedThreads()
    // 查询是否有些线程正在等待与此锁有关的给定条件。
    boolean hasWaiters(Condition condition)
    // 如果是“公平锁”返回true,否则返回false。
    boolean isFair()
    // 查询当前线程是否保持此锁。
    boolean isHeldByCurrentThread()
    // 查询此锁是否由任意线程保持。
    boolean isLocked()
    // 获取锁。
    void lock()
    // 如果当前线程未被中断,则获取锁。
    void lockInterruptibly()
    // 返回用来与此 Lock 实例一起使用的 Condition 实例。
    Condition newCondition()
    // 仅在调用时锁未被另一个线程保持的情况下,才获取该锁。
    boolean tryLock()
    // 如果锁在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁。
    boolean tryLock(long timeout, TimeUnit unit)
    // 试图释放此锁。
    void unlock()
    View Code

    举个栗子

    public class ConditionTest {
        private static Lock lock = new ReentrantLock();
        private static Condition condition = lock.newCondition();
        public static void main(String[] args) {
            ThreadA ta = new ThreadA("t");
            lock.lock(); // 获取锁
            try {
                System.out.println(Thread.currentThread().getName() + " start ta");
                ta.start();
                System.out.println(Thread.currentThread().getName() + " block");
                condition.await(); // 等待
                System.out.println(Thread.currentThread().getName() + " continue");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock(); // 释放锁
            }
        }
    
        static class ThreadA extends Thread {
            public ThreadA(String name) {
                super(name);
            }
    
            public void run() {
                lock.lock(); // 获取锁
                try {
                    try {
                        Thread.sleep(1000*5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " wakup others");
                    condition.signalAll(); // 唤醒“condition所在锁上的其它线程”
                } finally {
                    lock.unlock(); // 释放锁
                }
            }
        }
    }
    View Code

    源码分析

    lock-公平锁(FairSync extends Sync)

     final void lock() {
                acquire(1);
            }
    protected final boolean tryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {// c=0 说明没有其他线程占有锁
                    if (!hasQueuedPredecessors() &&
                        compareAndSetState(0, acquires)) {// 队列中没有其他线程在等待锁,而且CAS把state设置成入参的值成功,这里是1(这里的CAS就是我
    // 们前文提的并发竞争机制),则当前线程获取锁成功并将owner线程设置为当前线程
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                else if (current == getExclusiveOwnerThread()) {// 可重入设置,当前线程重复请求锁成功,只是增加请求锁的计数
                    int nextc = c + acquires;
                    if (nextc < 0)
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }

    lock-非公平锁(NonfairSync extends Sync)

     final void lock() {
                if (compareAndSetState(0, 1))//先去cas设置锁
                    setExclusiveOwnerThread(Thread.currentThread());
                else
                    acquire(1);//获取锁失败,再try
            }
     protected final boolean tryAcquire(int acquires) {
                return nonfairTryAcquire(acquires);
            }
     final boolean nonfairTryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {//如果当前没有线程持有锁,不管等待队列里有没有等待的线程,都直接去请求锁
                    if (compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                else if (current == getExclusiveOwnerThread()) {//可重入
                    int nextc = c + acquires;
                    if (nextc < 0) // overflow
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }

    unlock (公平锁和非公平锁的实现是一样的)

     public void unlock() {
            sync.release(1);
        }
    public final boolean release(int arg) {
    /*
     尝试释放锁如果失败,直接返回失败,如果成功并且head的状态不等于0就唤醒后面等待的节点
    */
            if (tryRelease(arg)) {
                Node h = head;
                if (h != null && h.waitStatus != 0)
                    unparkSuccessor(h);
                return true;
            }
            return false;
        }
    protected final boolean tryRelease(int releases) {
                // 释放后c的状态值
                int c = getState() - releases;
               // 如果持有锁的线程不是当前线程,直接抛出异常
                if (Thread.currentThread() != getExclusiveOwnerThread())
                    throw new IllegalMonitorStateException();
                boolean free = false;
                if (c == 0) {
                   // 如果c==0,说明所有持有锁都释放完了,其他线程可以请求获取锁
                    free = true;
                    setExclusiveOwnerThread(null);
                }
               // 这里只会有一个线程执行到这,不存在竞争,因此不需要CAS
                setState(c);
                return free;
            }
  • 相关阅读:
    递归函数底层原理浅析
    lambda expression & mutable
    命令mv
    printf的参数
    程序结构之静态本地变量
    汇编.align指令
    程序结构之全局变量
    命令touch
    更改gcc默认版本,实现gcc版本升降级
    命令chmod
  • 原文地址:https://www.cnblogs.com/amei0/p/9021899.html
Copyright © 2020-2023  润新知