定义:一个资源能够被多个读线程访问,或者被一个写线程访问,但是不能同时存在读写线程。读写互斥,读读共享。
示例代码:
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
class MyResource{
Map<String,String> map = new HashMap<>();
// 等价于 synchronized
Lock lock = new ReentrantLock();
// 一体两面,读写互斥,读读共享
ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
public void write(String key, String value) {
rwLock.writeLock().lock();
try{
System.out.println(Thread.currentThread().getName() + "\t" + "正在写入");
map.put(key, value);
try{ TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + "\t" + "完成写入");
}finally {
rwLock.writeLock().unlock();
}
}
public void read(String key) {
rwLock.readLock().lock();
try{
System.out.println(Thread.currentThread().getName() + "\t" + "正在读取");
String result = map.get(key);
try{ TimeUnit.MILLISECONDS.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }
// 读未完成之前,读写锁中的写无法获得
// try{ TimeUnit.MILLISECONDS.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + "\t" + "完成读取" + "\t" + result);
}finally {
rwLock.readLock().unlock();
}
}
}
public class ReentrantReadWriteLockDemo {
public static void main(String[] args) {
MyResource myResource = new MyResource();
for (int i = 1; i<= 10; i++) {
String finalI = String.valueOf(i);
new Thread(()-> {
myResource.write(finalI,finalI);
},"写锁-" + i).start();
}
for (int i = 1; i<= 10; i++) {
String finalI = String.valueOf(i);
new Thread(()-> {
myResource.read(finalI);
},"读锁-" + i).start();
}
}
}
锁降级:
将写入锁降级为读锁,重入锁允许再获取写锁之后,可再获取读锁。
- 如果同一个线程持有写锁,在没有释放写锁的情况下,它还可以继续获取读锁。这就是写锁的降级,降级称为了读锁
- 规则管理,先获取写锁,然后获取读锁,再释放写锁的次序
- 如果释放了写锁,那么就完成转换为读锁
锁降级代码演示:
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class LockDownGradingDemo {
public static void main(String[] args) {
ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
// 锁降级
// writeLock.lock();
// System.out.println("---写入");
// readLock.lock();
// System.out.println("---读取");
// writeLock.unlock();
// readLock.unlock();
// 无法锁升级,需要先释放读锁,才能获得写锁
readLock.lock();
System.out.println("---读取");
writeLock.lock();
System.out.println("---写入");
readLock.unlock();
writeLock.unlock();
}
}