ReadWriteLock是Jdk5中提供读写分离锁,读写分离锁可以有效地帮助减少锁竞争,提升系统性能。如果使用重用锁或内部锁,理论上所有读之间、读写之间、写和写之间都是串行操作。然而读写所允许多个线程同时读,读写操作或者写写操作仍然需要相互等待和持有锁。在系统中如果读操作次数远远大于写操作次数,读写锁就可以发挥最大功效,提升系统性能。
ReentrantLock
import org.junit.Test;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestReadWriteLock {
private static final int MAX_THREADS = 2000;
private static final int TASK_COUNT = 4000;
private static Lock lock = new ReentrantLock();
java.util.Random rand = new java.util.Random();
private int value;
/**
* ReentrantLock操作线程
*/
public class ReadWriteThread implements Runnable {
protected String name;
public ReadWriteThread() {
}
public ReadWriteThread(String name) {
this.name = name;
}
@Override
public void run() {
try {
handleRead();
int v = rand.nextInt(100);
if (v < 10) {
handleWrite(v);
}
Thread.sleep(rand.nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 线程池
*/
public class CounterPoolExecutor extends ThreadPoolExecutor {
private AtomicInteger count = new AtomicInteger(0);
public long startTime = 0;
public String funcname = "";
public CounterPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
protected void afterExecute(Runnable r, Throwable t) {
int l = count.addAndGet(1);
if (l == TASK_COUNT) {
System.out.println(funcname + " spend time:" + (System.currentTimeMillis() - startTime));
}
}
}
/**
* ReentrantLock可重入锁
*
* @return
* @throws InterruptedException
*/
public Object handleRead() throws InterruptedException {
try {
lock.lock();
Thread.sleep(1);
return value;
} finally {
lock.unlock();
}
}
/**
* ReentrantLock可重入锁
*
* @param index
* @throws InterruptedException
*/
public void handleWrite(int index) throws InterruptedException {
try {
lock.lock();
Thread.sleep(1);
value = index;
} finally {
lock.unlock();
}
}
/**
* 测试ReentrantLock
*
* @throws InterruptedException
*/
@Test
public void testLock() throws InterruptedException {
CounterPoolExecutor exe = new CounterPoolExecutor(MAX_THREADS, MAX_THREADS,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
long starttime = System.currentTimeMillis();
exe.startTime = starttime;
exe.funcname = "testLock";
for (int i = 0; i < TASK_COUNT; i++)
exe.submit(new ReadWriteThread());
Thread.sleep(100000);
}
}
输出结果
testLock spend time:6604
ReentrantReadWriteLock
import org.junit.Test;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class TestReadWriteLock {
private static final int MAX_THREADS = 2000;
private static final int TASK_COUNT = 4000;
private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private static Lock readLock = readWriteLock.readLock();
private static Lock writeLock = readWriteLock.writeLock();
java.util.Random rand = new java.util.Random();
private int value;
/**
* ReentrantReadWriteLock操作线程
*/
public class ReadWriteThread2 implements Runnable {
protected String name;
public ReadWriteThread2() {
}
public ReadWriteThread2(String name) {
this.name = name;
}
@Override
public void run() {
try {
handleRead2();
int v = rand.nextInt(100);
if (v < 10) {
handleWrite2(v);
}
Thread.sleep(rand.nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 线程池
*/
public class CounterPoolExecutor extends ThreadPoolExecutor {
private AtomicInteger count = new AtomicInteger(0);
public long startTime = 0;
public String funcname = "";
public CounterPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
protected void afterExecute(Runnable r, Throwable t) {
int l = count.addAndGet(1);
if (l == TASK_COUNT) {
System.out.println(funcname + " spend time:" + (System.currentTimeMillis() - startTime));
}
}
}
/**
* ReentrantReadWriteLock
*
* @return
* @throws InterruptedException
*/
public Object handleRead2() throws InterruptedException {
try {
readLock.lock();
Thread.sleep(1);
return value;
} finally {
readLock.unlock();
}
}
/**
* ReentrantReadWriteLock
*
* @param index
* @throws InterruptedException
*/
public void handleWrite2(int index) throws InterruptedException {
try {
writeLock.lock();
Thread.sleep(1);
value = index;
} finally {
writeLock.unlock();
}
}
/**
* 测试读写锁ReentrantReadWriteLock
*
* @throws InterruptedException
*/
@Test
public void testLock2() throws InterruptedException {
CounterPoolExecutor executor = new CounterPoolExecutor(MAX_THREADS, MAX_THREADS,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
long starttime = System.currentTimeMillis();
executor.startTime = starttime;
executor.funcname = "testLock2";
for (int i = 0; i < TASK_COUNT; i++) {
executor.submit(new ReadWriteThread2());
}
Thread.sleep(100000);
}
}
输出结果
testLock2 spend time:1102