结论:Java中ReentrantReadWriteLock对写互斥,对读共享。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockTest {
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
final Lock readLock = readWriteLock.readLock();
final Lock writeLock = readWriteLock.writeLock();
public static void main(String[] args) throws InterruptedException {
// new ReadWriteLockTest().writeRead();
// new ReadWriteLockTest().readRead();
// new ReadWriteLockTest().readWrite();
// new ReadWriteLockTest().writeWrite();
new ReadWriteLockTest().writeReadWrite();
}
/**
* 读 -> 写。同时有写锁和读锁时,写锁必须阻塞等待读锁读完,写锁才能进去。
* @throws InterruptedException
*/
private void readWrite() throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(String.format("tid[%s]: w请求读锁", Thread.currentThread().getId()));
readLock.lock();
System.out.println(String.format("tid[%s]: w获得读锁", Thread.currentThread().getId()));
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(String.format("tid[%s]: w释放读锁", Thread.currentThread().getId()));
readLock.unlock();
}
}
}).start();
// 为了保证顺序,休眠一会再调度
Thread.sleep(100);
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(String.format("tid[%s]: w请求写锁", Thread.currentThread().getId()));
writeLock.lock();
System.out.println(String.format("tid[%s]: w获得写锁", Thread.currentThread().getId()));
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(String.format("tid[%s]: w释放写锁", Thread.currentThread().getId()));
writeLock.unlock();
}
}
}).start();
}
/**
* 写 -> 读 -> 写。
* 后面写锁是否会优先调度?答:不会,还是会按顺序调度
* @throws InterruptedException
*/
private void writeReadWrite() throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(String.format("tid[%s]: w请求写锁", Thread.currentThread().getId()));
writeLock.lock();
System.out.println(String.format("tid[%s]: w获得写锁", Thread.currentThread().getId()));
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(String.format("tid[%s]: w释放写锁", Thread.currentThread().getId()));
writeLock.unlock();
}
}
}).start();
// 为了保证顺序,休眠一会再调度
Thread.sleep(100);
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(String.format("tid[%s]: w请求读锁", Thread.currentThread().getId()));
readLock.lock();
System.out.println(String.format("tid[%s]: w获得读锁", Thread.currentThread().getId()));
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(String.format("tid[%s]: w释放读锁", Thread.currentThread().getId()));
readLock.unlock();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(String.format("tid[%s]: w请求写锁", Thread.currentThread().getId()));
writeLock.lock();
System.out.println(String.format("tid[%s]: w获得写锁", Thread.currentThread().getId()));
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(String.format("tid[%s]: w释放写锁", Thread.currentThread().getId()));
writeLock.unlock();
}
}
}).start();
}
/**
* 写 -> 读。同时有写锁和读锁时,读锁必须等待写锁写完后,才能获得锁
* @throws InterruptedException
*/
private void writeRead() throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(String.format("tid[%s]: w请求写锁", Thread.currentThread().getId()));
writeLock.lock();
System.out.println(String.format("tid[%s]: w获得写锁", Thread.currentThread().getId()));
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(String.format("tid[%s]: w释放写锁", Thread.currentThread().getId()));
writeLock.unlock();
}
}
}).start();
// 为了保证顺序,休眠一会再调度
Thread.sleep(100);
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(String.format("tid[%s]: w请求读锁", Thread.currentThread().getId()));
readLock.lock();
System.out.println(String.format("tid[%s]: w获得读锁", Thread.currentThread().getId()));
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(String.format("tid[%s]: w释放读锁", Thread.currentThread().getId()));
readLock.unlock();
}
}
}).start();
}
/**
* 读 -> 读,读锁可以共享
*/
private void readRead() {
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(String.format("tid[%s]: w请求读锁", Thread.currentThread().getId()));
readLock.lock();
System.out.println(String.format("tid[%s]: w获得读锁", Thread.currentThread().getId()));
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(String.format("tid[%s]: w释放读锁", Thread.currentThread().getId()));
readLock.unlock();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(String.format("tid[%s]: w请求读锁", Thread.currentThread().getId()));
readLock.lock();
System.out.println(String.format("tid[%s]: w获得读锁", Thread.currentThread().getId()));
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(String.format("tid[%s]: w释放读锁", Thread.currentThread().getId()));
readLock.unlock();
}
}
}).start();
}
/**
* 写 -> 写。同时有写锁和写锁时,写锁必须等待上一个写锁写完后,才能获得锁
* @throws InterruptedException
*/
private void writeWrite() throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(String.format("tid[%s]: w请求写锁", Thread.currentThread().getId()));
writeLock.lock();
System.out.println(String.format("tid[%s]: w获得写锁", Thread.currentThread().getId()));
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(String.format("tid[%s]: w释放写锁", Thread.currentThread().getId()));
writeLock.unlock();
}
}
}).start();
// 为了保证顺序,休眠一会再调度
Thread.sleep(100);
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(String.format("tid[%s]: w请求写锁", Thread.currentThread().getId()));
writeLock.lock();
System.out.println(String.format("tid[%s]: w获得写锁", Thread.currentThread().getId()));
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(String.format("tid[%s]: w释放写锁", Thread.currentThread().getId()));
writeLock.unlock();
}
}
}).start();
}
}