读写锁
ReentrantReadWriteLock
当读操作远远高于写操作时,这时候使用读写锁让读-读可以并发,提高性能。
读读并发:
public static void main(String[] args) {
ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
for(int i=0;i<10;i++){
new Thread(() -> {
rwLock.readLock().lock();
try {
log.info("读取信息中。。。");
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}finally {
rwLock.readLock().unlock();
}
}).start();
}
}
读写不并发:
public static void main(String[] args) {
ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
new Thread(() -> {
rwLock.writeLock().lock();
try {
log.info("写入信息中。。。");
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
rwLock.writeLock().unlock();
}
}).start();
new Thread(() -> {
rwLock.readLock().lock();
try {
log.info("读取信息中。。。");
} finally {
rwLock.readLock().unlock();
}
}).start();
}
StampedLock
该类自 JDK 8 加入,是为了进一步优化读性能,它的特点是在使用读锁、写锁时都必须配合【戳】使用
class DataContainerStamped {
private int data;
private final StampedLock lock = new StampedLock();
public DataContainerStamped(int data) {
this.data = data;
}
public int read(int readTime) {
long stamp = lock.tryOptimisticRead();
log.debug("optimistic read locking...{}", stamp);
sleep(readTime);
if (lock.validate(stamp)) {
log.debug("read finish...{}, data:{}", stamp, data);
return data;
}
// 锁升级 - 读锁
log.debug("updating to read lock... {}", stamp);
try {
stamp = lock.readLock();
log.debug("read lock {}", stamp);
sleep(readTime);
log.debug("read finish...{}, data:{}", stamp, data);
return data;
}
finally {
log.debug("read unlock {}", stamp);
lock.unlockRead(stamp);
}
}
public void write(int newData) {
long stamp = lock.writeLock();
log.debug("write lock {}", stamp);
try {
sleep(2);
this.data = newData;
}
finally {
log.debug("write unlock {}", stamp);
lock.unlockWrite(stamp);
}
}
}