什么是读写锁?
读 | 写 | |
---|---|---|
读 | 非阻塞 | 阻塞 |
写 | 阻塞 | 阻塞 |
如果读操作频率远高于写操作,那读写锁就能大大提升系统性能
看两组对比例子:
先定义一个线程池,2000核心线程,4000最大线程,当所有线程执行结束之后,计算耗时
public class TestPoolExecutor extends ThreadPoolExecutor {
private AtomicInteger count =new AtomicInteger(0);
public long startTime=0;
public TestPoolExecutor() {
super(2000, 4000, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
}
protected void afterExecute(Runnable r, Throwable t) {
int l=count.addAndGet(1);
if(l==2000){
System.out.println("用时:"+(System.currentTimeMillis()-startTime));
}
}
}
模拟多线程下读写,读操作1% 写操作99%,每次读写操作耗时1ms
,提交10000次读写任务,看看两者的性能差异
- 使用
ReentrantLock
的情况下
public class TestReentrantLock {
private static Lock lock=new ReentrantLock();
static Random rand=new Random();
private static int value;
public static class ReadWriteThread implements Runnable{
protected String name;
public ReadWriteThread(){
}
@Override
public void run() {
try {
read();
int v=rand.nextInt(1000);
if(v<10)
write(v);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public Object read() throws InterruptedException{
try{
lock.lock();
Thread.sleep(1);
return value;
}finally{
lock.unlock();
}
}
public void write(int index) throws InterruptedException{
try{
lock.lock();
Thread.sleep(1);
value=index;
}finally{
lock.unlock();
}
}
}
public static void main(String[] args) {
TestPoolExecutor exe=new TestPoolExecutor();
long startTime=System.currentTimeMillis();
exe.startTime=startTime;
for(int i=0;i<10000;i++)
exe.submit(new ReadWriteThread());
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
本人笔记本耗时为:3649ms
- 使用
ReentrantReadWriteLock
public class TestReadWriteLock {
private static ReentrantReadWriteLock readWriteLock=new ReentrantReadWriteLock();
private static Lock readLock = readWriteLock.readLock();
private static Lock writeLock = readWriteLock.writeLock();
static Random rand=new Random();
private static int value;
public static class ReadWriteThread implements Runnable{
public ReadWriteThread(){
}
@Override
public void run() {
try {
read();
int v=rand.nextInt(1000);
if(v<10)
write(v);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public Object read() throws InterruptedException{
try{
readLock.lock();
Thread.sleep(1);
return value;
}finally{
readLock.unlock();
}
}
public void write(int index) throws InterruptedException{
try{
writeLock.lock();
Thread.sleep(1);
value=index;
}finally{
writeLock.unlock();
}
}
}
public static void main(String[] args) {
TestPoolExecutor exe=new TestPoolExecutor();
exe.startTime=System.currentTimeMillis();
for(int i=0;i<10000;i++)
exe.submit(new ReadWriteThread());
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
本人笔记本耗时为:174ms
对于读写锁而言,读操作越耗时,性能提升越明显,将读操作模拟耗时5ms
,写操作不变
使用ReentrantLock
本人笔记本耗时为:11554ms
而TestReadWriteLock
只需要:197ms