主要有读写锁和可重入锁两个重要的实现。
1 2 3 4 5 6 7 8 9 10
| public interface Lock { void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit unit) throws InterruptedException; void unlock(); Condition newCondition(); }
|
ReentrantLock
ReentrantLock 实现了 Lock接口,Lock接口中定义了 lock与 unlock相关操作,并且还存在 newCondition方法,表示生成一个条件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; abstract void lock(); 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) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; } protected final boolean isHeldExclusively() { return getExclusiveOwnerThread() == Thread.currentThread(); } final ConditionObject newCondition() { return new ConditionObject(); } final Thread getOwner() { return getState() == 0 ? null : getExclusiveOwnerThread(); } final int getHoldCount() { return isHeldExclusively() ? getState() : 0; } final boolean isLocked() { return getState() != 0; } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); } }
|
独享锁、支持公平锁和非公平锁两种模式,可重入锁。

初始时持有者为null,计数是当前调用lock()方法加锁的次数,unlock()会将计数减1,当计数为0时,则表示当前锁被释放。(获取当前锁的次数 getHoldCount())
可重入锁的话,做了一次加锁就一定要有对应的一次解锁,否则产生死锁。
ReadWriteLock(注:不是Lock锁的子类)
维护一对关联锁,一个用于只读操作,一个用于写入;读锁可以由多个读线程同时持有,写锁是排他的。
读锁拒绝其他线程获得写锁,读锁不拒绝其他线程获得读锁,多个上了读锁的线程可以并发读不会阻塞。多个读锁同时作用期间,其他想上写锁的线程都处在等待状态,当最后一个读锁释放后,才有可能上锁。
适合读取线程比写入线程多的场景,改进互斥锁的性能,示例场景:缓存组件、集合的并发线程安全性改造。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| public class LockDemo2 { ReadWriteLock lock = new ReentrantReadWriteLock();
public static void main(String[] args) { LockDemo2 lockDemo2 = new LockDemo2();
for (int i = 0; i < 2; i++) { new Thread(() -> { lockDemo2.read(Thread.currentThread()); }, "A" + i).start(); }
new Thread(() -> { lockDemo2.write(Thread.currentThread()); }, "C").start(); }
public void read(Thread t) { lock.readLock().lock(); try { long start = System.currentTimeMillis(); while (System.currentTimeMillis() - start <= 1) { System.out.println(t.getName() + "正在【读】操作"); } System.out.println(t.getName() + "【读】操作完成"); } finally { lock.readLock().unlock(); } }
public void write(Thread t) { lock.writeLock().lock(); try { long start = System.currentTimeMillis(); while (System.currentTimeMillis() - start <= 1) { System.out.println(t.getName() + "正在【写】操作"); } System.out.println(t.getName() + "【写】操作完成"); } finally { lock.writeLock().unlock(); } } }
|
ReadWriteLock锁降级
锁降级指的是写锁降级成为读锁。把持住当前拥有的写锁的同时,再获取到读锁,随后释放写锁的过程。
写锁是线程独占,读锁是共享,所以写->读是升级。(读~>写, 是不能实现的)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
public class LockDemo3 { private Map<String, Object> cache = new HashMap<>(); private ReadWriteLock rwl = new ReentrantReadWriteLock();
public Object getData(String key) { rwl.readLock().lock(); Object value = null; try { value = cache.get(key); if (value == null) { rwl.readLock().unlock(); rwl.writeLock().lock(); try { if (value == null) { value = "XXX"; } } finally { rwl.writeLock().unlock(); } rwl.readLock().lock(); } } finally { value = cache.get(key); rwl.readLock().unlock(); } return value; } }
|
Condition
