Java多线程 ReadWriteLock、StampedLock用法
无论是synchronized机制,还是ReentrantLock加锁,实际上只有一个线程可以执行临界区代码。即读写、写读、读读、写写 两个线程之间是相互阻塞的。然而读线程之间是需要并发的,Java使用ReadWriteLock实现多个线程同时读提高并发性能。
1、ReadWriteLock
import java.util.Arrays; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class RWLock { public static void main(String[] args) { var point = new Pixel(); Thread t1 = new Thread() { @Override public void run() { for (int i = 0; i < 10; i++) { point.move(i, i); } } }; t1.start(); for (int j = 0; j < 10; j++) { Thread t = new Thread() { @Override public void run() { point.getPosition(); } }; t.start(); } } } class Pixel { private int[] position = { 0, 0 }; private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final Lock writeLock = lock.writeLock(); private final Lock readLock = lock.readLock(); public void move(int i, int j) { writeLock.lock(); try { this.position[0] = i; this.position[1] = j; } finally { writeLock.unlock(); } } public void getPosition() { readLock.lock(); try { System.out.println(Arrays.toString(this.position)); } finally { readLock.unlock(); } } }
ReadWriteLock 的用法:在需要加写锁的地方调用 writeLock.lock(); 在需要加读锁的地方调用 readLock.lock();
ReadWriteLock保证多个线程可以同时获取读锁,但读写,写读,写写线程之间仍然是阻塞的。
2、StampedLock
由于ReadWriteLock在读的过程中不允许写,这是一种悲观的读锁,Java 8引入了新的读写锁 StampedLock,允许读的过程中写入,这是一种乐观的读锁。
class Point { private final StampedLock stampedLock = new StampedLock(); private double x; private double y; public void move(double x1, double y1) { long stamp = stampedLock.writeLock(); try { this.x += x1; this.y += y1; } finally { stampedLock.unlock(stamp); } } public double getDistance() { long stamp = stampedLock.tryOptimisticRead(); double x2 = this.x; double y2 = this.y; if (stampedLock.validate(stamp)) { stamp = stampedLock.readLock(); try { x2 = this.x; y2 = this.y; } finally { stampedLock.unlock(stamp); } } return Math.sqrt(x2 * x2 + y2 * y2); } }
需要注意的是:
1、StampedLock 获取锁的方法会返回一个邮戳(Stamp);
2、释放锁的方法也需要一个邮戳(Stamp);
3、StampedLock是不可重入的;
4、StampedLock有三种访问模式:
- Reading(读模式):功能和ReentrantReadWriteLock的读锁类似
- Writing(写模式):功能和ReentrantReadWriteLock的写锁类似
- Optimistic reading(乐观读模式):这是一种优化的读模式。
5、StampedLock支持读锁和写锁的相互转换;
6、无论写锁还是读锁,都不支持Conditon等待。
参考链接:
https://segmentfault.com/a/1190000015808032
https://www.liaoxuefeng.com/wiki/1252599548343744/1309138673991714