Java多线程(二十一)---Java中的锁---读写锁

2018-08-27  本文已影响65人  凯玲之恋

移步java多线程系列文章

1 概述

2 读写锁的接口与示例

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();
            }
    }
}

3 读写锁的实现分析

分析ReentrantReadWriteLock的实现,主要包括:读写状态的设计、写锁的获取与释放、读锁的获取与释放以及锁降级(以下没有特别说明读写锁均可认为是ReentrantReadWriteLock)。

3.1 读写状态的设计

3.2 写锁的获取和释放

protected final boolean tryAcquire(int acquires) {
    Thread current = Thread.currentThread();
    int c = getState();
    int w = exclusiveCount(c);
    if (c != 0) {
            // 存在读锁或者当前获取线程不是已经获取写锁的线程
            if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
            if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
            setState(c + acquires);
            return true;
    }
    if (writerShouldBlock() || !compareAndSetState(c, c + acquires)) {
            return false;
    }
    setExclusiveOwnerThread(current);
    return true;
}

3.3 读锁的获取与释放

protected final int tryAcquireShared(int unused) {
    for (;;) {
            int c = getState();
            int nextc = c + (1 << 16);
            if (nextc < c)
                    throw new Error("Maximum lock count exceeded");
            if (exclusiveCount(c) != 0 && owner != Thread.currentThread())
                    return -1;
            if (compareAndSetState(c, nextc)) 
                    return 1;
    }
}

3.4 锁降级

接下来看一个锁降级的示例。

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();
    }
}

参考

《java并发编程的艺术》

上一篇下一篇

猜你喜欢

热点阅读