Java

【并发编程】- 锁篇

2021-01-18  本文已影响0人  双木ll之林

1)synchronized关键字与java.util.concurrent.locks的lock接口

    Lock lock = new ReentrantLock();
    lock.lock();
    try {
    } finally {
        lock.unlock();
    }

不要将获取锁的过程写在try块中,因为如果在获取锁(自定义锁的实现)时发生了异常,异常抛出的同时,也会导致锁无故释放。


节点的属性类型与名称以及描述
同步队列结构图 CAS设置尾结点图 首节点的设置图
  • 过早通知:指前驱节点不是头节点的线程由于中断而被唤醒
节点自旋获取同步状态图
    /**
     * 1.tryAcquire保证线程安全的获取同步状态(CAS)
     * 2.假如1获取失败,以独占式Node.EXCLUSIVE构造同步节点,即是一个同个时刻只能有一个线程成功获取同步状态,并通过addWaiter(Node node)方法将该节点加入到同步队列的尾部
     * 3.调用acquireQueued(Node node,intarg)方法(自旋),使得该节点以“死循环”的方式获取同步状态
     */
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

总结

  • 在获取同步状态时,同步器维护一个同步队列,获取状态失败的线程都会被加入到队列中并在队列中进行自旋;
  • 移出队列(或停止自旋)的条件是前驱节点为头节点且成功获取了同步状态。在释放同步状态时同步器调用tryRelease(int arg)方法释放同步状态,然后唤醒头节点的后继节点。


public class Cache {
        static Map<String, Object> map = new HashMap<String, Object>();
        static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
        static Lock r = rwl.readLock();
        static Lock w = rwl.writeLock();

        // 获取一个key对应的value
        public static final Object get(String key) {
            r.lock();
            try {
                return map.get(key);
            } finally {
                r.unlock();
            }
        }

        // 设置key对应的value,并返回旧的value
        public static final Object put(String key, Object value) {
            //其他线程对于读锁和写锁的均被阻塞
            w.lock();
            try {
                return map.put(key, value);
            } finally {
                w.unlock();
            }
        }

        // 清空所有的内容
        public static final void clear() {
            w.lock();
            try {
                map.clear();
            } finally {
                w.unlock();
            }
        }
    }
 public void processData() {
        readLock.lock();
        if (!update) {
            // 必须先释放读锁
            readLock.unlock();
            // 锁降级从写锁获取到开始
            writeLock.lock();
            try {
                if (!update) {
                    // 准备数据的流程(略)
                    update = true;
                }
                readLock.lock();
            } finally {
                writeLock.unlock();
            }
            // 锁降级完成,写锁降级为读锁
        }
        try {
            // 使用数据的流程(略)
        } finally {
            readLock.unlock();
        }
    }
Object的监视器方法与Condition接口的对比
上一篇下一篇

猜你喜欢

热点阅读