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


| 12
 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()就能分别获取到读锁,和写锁了。接着我们这要者对应的地方加入对应的锁即可。在写操作时加入写锁,读操作时加入读锁。修改代码


运行查看结果,写操作只能一个线程执行,必须执行完成后才能做其他操作。读操作可以多个线程同时进行。
| 12
 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();
 }
 }
 }
 
 |