JDK1.5以后,提供读写锁。这种锁支持多线程读操作不互斥,多线程读与写互斥,多线程写与写互斥,但读与读操作并不互斥。这样有助于性能的提高。
我们对数据的操作无非两种:“读”和“写”,试想一个这样的情景,当十个线程同时读取某个数据时,这个操作应不应该加同步。所以我们使用ReentrantReadWriteLockt它是一个解决单线程写和多线程读的理想方法。它采用类似于读写分离的思路设定了读锁和写锁。对于这两个锁的访问保证尽可能大的读并行和写互斥。另外,在一定的条件下写锁可以转换成读锁,而读锁却不能转换成写锁。
上代码:
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
//资源类
class MyCache{
private Map<String,Object> map = new ConcurrentHashMap<>();
private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
//读写分离
//模拟写操作
void Write(String key, Object value){
readWriteLock.writeLock().lock();
try{
System.out.println(Thread.currentThread().getName() +"\t 正在写入..."+",值为:"+key);
try {
TimeUnit.SECONDS.sleep(2);
}catch (Exception e){
e.printStackTrace();
}
map.put(key,value);
System.out.println(Thread.currentThread().getName() +"\t 写入完毕!");
}catch (Exception e){
e.printStackTrace();
}finally {
readWriteLock.writeLock().unlock();
}
}
void Read(String key){
readWriteLock.readLock().lock();
try{
System.out.println(Thread.currentThread().getName() +"\t 正在读取...");
Object res = map.get(key);
System.out.println(Thread.currentThread().getName()+"\t 读到的值为:"+res);
}catch (Exception e){
e.printStackTrace();
}finally {
readWriteLock.readLock().unlock();
}
}
}
public class ReadAndWriteLockDemo {
public static void main(String[] args) {
MyCache cache = new MyCache();
//模拟五个线程写入值
for (int i = 1; i <= 5; i++) {
final int tmp = i;
new Thread(() -> {
cache.Write(tmp + "", tmp + "");
}, "写线程" + i).start();
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+",我静静地看着它们....");
//模拟五个线程正在读
for (int i = 1; i <=5 ; i++) {
final int tmp = i;
new Thread(()->{
cache.Read(tmp+"");
},"读线程"+ i).start();
}
}
}