我们以前理解的锁,基本都是排他锁,也就是这些锁在同一时刻只允许一个线程进行访问,而读写所在同一时刻可 以允许多个线程访问,但是在写线程访问时,所有的读线程和其他写线程都会被阻塞。读写锁维护了一对锁,一个 读锁、一个写锁; 一般情况下,读写锁的性能都会比排它锁好,因为大多数场景读是多于写的。在读多于写的情况 下,读写锁能够提供比排它锁更好的并发性和吞吐量.
package com.example.demo.morethread;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 读写锁
*/
public class ReentrantReadWriteDemo {
static Map<String, Object> cacheMap = new HashMap<String, Object>();
static ReentrantReadWriteLock rw = new ReentrantReadWriteLock();
static Lock read = rw.readLock();
static Lock write = rw.writeLock();
public static final Object get(String key) {
read.lock();
System.out.println(Thread.currentThread().getName() + ":开始读数据" + key + ":" + cacheMap.get(key));
try {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return cacheMap.get(key);
} finally {
System.out.println(Thread.currentThread().getName() + ":读取结束" + key + ":" + cacheMap.get(key));
read.unlock();
}
}
public static final void put(String key,Object value){
write.lock();
System.out.println(Thread.currentThread().getName()+":开始写数据"+key+":"+value);
try {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cacheMap.put(key, value);
}finally {
System.out.println(Thread.currentThread().getName()+":写数据结束"+key+":"+value);
write.unlock();
}
}
}
package com.example.demo.morethread;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteDemoTest {
public static void main(String[] args) throws InterruptedException{
new Thread(()->{ReentrantReadWriteDemo.put("name","xiaoming");
},"write_thread1").start();
new Thread(()->{ReentrantReadWriteDemo.put("age","29");
},"write_thread2").start();
new Thread(()->{ReentrantReadWriteDemo.get("name");
},"read_thread1").start();
new Thread(()->{ReentrantReadWriteDemo.get("name");
},"read_thread2").start();
new Thread(()->{ReentrantReadWriteDemo.get("name");
},"read_thread3").start();
new Thread(()->{ReentrantReadWriteDemo.put("sex","male");
},"write_thread3").start();
new Thread(()->{ReentrantReadWriteDemo.get("age");
},"read_thread12").start();
new Thread(()->{ReentrantReadWriteDemo.get("age");
},"read_thread22").start();
new Thread(()->{ReentrantReadWriteDemo.get("age");
},"read_thread32").start();
new Thread(()->{ReentrantReadWriteDemo.get("sex");
},"read_thread11").start();
new Thread(()->{ReentrantReadWriteDemo.get("sex");
},"read_thread21").start();
new Thread(()->{ReentrantReadWriteDemo.get("sex");
},"read_thread31").start();
}
}
运行结果如下:
在这个案例中,通过hashmap来模拟了一个内存缓存,然后使用读写所来保证这个内存缓存的线程安全性。当执 行读操作的时候,需要获取读锁,在并发访问的时候,读锁不会被阻塞,因为读操作不会影响执行结果。
在执行写操作是,线程必须要获取写锁,当已经有线程持有写锁的情况下,当前线程会被阻塞,只有当写锁释放以 后,其他读写操作才能继续执行。使用读写锁提升读操作的并发性,也保证每次写操作对所有的读写操作的可见性
读锁与读锁可以共享
读锁与写锁不可以共享(排他)
写锁与写锁不可以共享(排他)