ReadWriteLock 读写锁 又叫排他锁
如果使用互斥锁,一个线程在读,其他线程也不能读也不能写
换成读写锁的时候,读线程是读锁,写线程是写锁,写锁是排他的
在多线程大大提高效率,当一个线程在读的时候,其他线程也可以进来继续读
import java.util.Random;
import java.util.concurrent.atomic.LongAdder;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class T10_TestReadWriteLock {
static Lock lock = new ReentrantLock();
private static int value;
static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
static Lock readLock = readWriteLock.readLock();
static Lock writeLock = readWriteLock.writeLock();
public static void read(Lock lock) {
try {
lock.lock();
Thread.sleep(1000);
System.out.println("read over!");
//模拟读取操作
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void write(Lock lock, int v) {
try {
lock.lock();
Thread.sleep(1000);
value = v;
System.out.println("write over!");
//模拟写操作
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
//Runnable readR = ()-> read(lock);
Runnable readR = ()-> read(readLock);
//Runnable writeR = ()->write(lock, new Random().nextInt());
Runnable writeR = ()->write(writeLock, new Random().nextInt());
for(int i=0; i<18; i++) new Thread(readR).start();
for(int i=0; i<2; i++) new Thread(writeR).start();
}
}
使用ReentrantLock 20s
使用ReentrantReadWriteLock 2s
目前有 18 个线程执行读操作,每个读操作需要 1 秒钟执行,同时有 2 个线程执行写操作,每个写操作也需要 1 秒钟执行。
因为读操作是共享锁(读锁),多个线程可以同时获得读锁,但写操作是独占锁(写锁),只有一个线程能获得写锁,其他线程需要等待。
根据代码逻辑,18 个读线程并发执行,每个读线程需要 1 秒执行完毕,因为读操作是并发执行的,所以整体读操作的时间是 1 秒。
同时,2 个写线程需要依次获取写锁执行写操作,每个写线程也需要 1 秒执行完毕。由于写操作是独占锁,所以第一个写线程执行完毕后,第二个写线程才能获取到写锁执行写操作。
因此,整体来看,读线程总共需要 1 秒,写线程总共需要 2 秒(1 秒执行写操作,1 秒等待另一个写线程执行完毕),所以整个程序执行的时间大约是 2 秒左右。