使用JDK原生的ReentrantLock读写锁解决写操作并发问题
ReentrantLockDemo
测试类
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCache myCache = new MyCache();
for (int i = 1; i <= 5; i++) {
final int it = i;
new Thread(() ->{
myCache.set(it+"key",it+"value");
},String.valueOf(i)).start();
new Thread(() ->{
myCache.get(it+"key");
},String.valueOf(i)).start();
}
}
}
资源类(加锁之前)
class MyCache1 {
Map<String, Object> map = new HashMap<>();
ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
public void set(String key, Object value) {
System.out.println(Thread.currentThread().getName() + "正在写入" + key);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "写入完成");
}
public void get(String key) {
System.out.println(Thread.currentThread().getName() + "正在读取" + key);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object result = map.get(key);
System.out.println(Thread.currentThread().getName() + "读取结果:" + result);
}
}
测试结果:
写操作应该具有原子性,写操作不能与写操作并发,也不能与读并发。但是测试结果显示,写操作与其他的写操作或者读操作并发执行了。那么我们对资源类进行改造:
资源类(加锁之后)
class MyCache {
Map<String, Object> map = new HashMap<>();
ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
public void set(String key, Object value) {
try {
rwLock.writeLock().lock();
System.out.println(Thread.currentThread().getName() + "正在写入" + key);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
map.put(key,value);
System.out.println(Thread.currentThread().getName() + "写入完成");
} finally {
rwLock.writeLock().unlock();
}
}
public void get(String key) {
try {
rwLock.readLock().lock();
System.out.println(Thread.currentThread().getName() + "正在读取" + key);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
Object result = map.get(key);
System.out.println(Thread.currentThread().getName() + "读取结果:" +result);
} finally {
rwLock.readLock().unlock();
}
}
}
测试结果:
测试结果显示完美,写与写操作不能并发,写与读不能并发,读与读可以并发。
测试结果对比:
测试结果显示完美,写与写操作不能并发,写与读不能并发,读与读可以并发。
源码及其他并发demo见github