读写锁
读写锁是指两个锁,读锁和写锁。
写锁又称为独占锁,指该锁一次只能被一个线程所持有。ReentrantLock
和Synchronized
而言都是独占锁
读锁又称为共享锁,指该锁可以被多个线程所持有。
使用场景
当我们需要写的时候必须等我们写入完成了才能被读取的时。也即是读操作可以多线程同时进行,写操作必须只能被一个线程进行的场景时。


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
| public class ReadWriteLockDemo {
public static void main(String[] args) { MyCache myCache = new MyCache();
for (int i = 1; i <= 5; i++) { final int temp = i; new Thread(() -> { myCache.put(temp + "", temp + ""); }, String.valueOf(i)).start(); }
for (int i = 1; i <= 5; i++) { final int temp = i; new Thread(() -> { myCache.get(temp + ""); }, String.valueOf(i)).start(); }
} }
class MyCache { private volatile Map<String, Object> map = new HashMap<>(); public void put(String key, Object value) { System.out.println(Thread.currentThread().getName() + "\t 正在写入:" + key); try { TimeUnit.MICROSECONDS.sleep(300); map.put(key, value); System.out.println(Thread.currentThread().getName() + "\t 写入完成!"); } catch (InterruptedException e) { e.printStackTrace(); } }
public void get(String key) { System.out.println(Thread.currentThread().getName() + "\t 正在读取"); try { TimeUnit.MICROSECONDS.sleep(300); Object result = map.get(key); System.out.println(Thread.currentThread().getName() + "\t 读取完成:" + result); } catch (InterruptedException e) { e.printStackTrace(); } } }
|
运行查看效果~

写操作还没有写完就已经被中断,做了其他的事。
为了解决这种问题我们就要用到我们的读写锁。JUC包下为我们提供了ReentrantReadWriteLock
获取读锁和写锁。


通过该类的readLock()
和writeLock()
就能分别获取到读锁,和写锁了。接着我们这要者对应的地方加入对应的锁即可。在写操作时加入写锁,读操作时加入读锁。修改代码


运行查看结果,写操作只能一个线程执行,必须执行完成后才能做其他操作。读操作可以多个线程同时进行。
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
|
public class ReadWriteLockDemo {
public static void main(String[] args) { MyCache myCache = new MyCache();
for (int i = 1; i <= 5; i++) { final int temp = i; new Thread(() -> { myCache.put(temp + "", temp + ""); }, String.valueOf(i)).start(); }
for (int i = 1; i <= 5; i++) { final int temp = i; new Thread(() -> { myCache.get(temp + ""); }, String.valueOf(i)).start(); }
} }
class MyCache { private volatile Map<String, Object> map = new HashMap<>(); private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void put(String key, Object value) { lock.writeLock().lock(); System.out.println(Thread.currentThread().getName() + "\t 正在写入:" + key); try { TimeUnit.MICROSECONDS.sleep(300); map.put(key, value); System.out.println(Thread.currentThread().getName() + "\t 写入完成!"); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.writeLock().unlock(); }
}
public void get(String key) { lock.readLock().lock(); System.out.println(Thread.currentThread().getName() + "\t 正在读取"); try { TimeUnit.MICROSECONDS.sleep(300); Object result = map.get(key); System.out.println(Thread.currentThread().getName() + "\t 读取完成:" + result); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.readLock().unlock(); } } }
|