ReentrantReadWriteLock
先写一段原始代码
public class Demo3 {
//共享变量
static int count = 0;
public static void readMethod() {
try {
// 为了展示出多线程同时操作同一数据会出现问题。如果去掉之后可能会正常计算出数据
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 当次访问读锁
Demo3.readMethod();
}
});
thread.start();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 当次访问读锁
Demo3.readMethod();
}
});
thread2.start();
Thread.sleep(20000);
System.out.println("result:" + count);
}
}
预计得值:result: 10000
实际运行得值:result: 9999(经过多次重试,发现小于等于10000)
我们来给它加上锁ReentrantReadWriteLock
当次两个线程都使用 读锁
public class Demo2 {
//共享变量
static int count = 0;
// 重入读写锁
static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
// 写锁
static Lock write = rwl.writeLock();
// 读锁
static Lock read = rwl.readLock();
//当前方法使用读锁
public static void readMethod() {
read.lock(); //读锁
try {
// 为了展示出多线程同时操作同一数据会出现问题。如果去掉之后可能会正常计算出数据
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
read.unlock(); //释放读锁
}
}
//当前方法使用读锁
public static void writeMethod() {
write.lock(); //Other
try {
// 为了展示出多线程同时操作同一数据会出现问题。如果去掉之后可能会正常计算出数据
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
write.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 当次访问读锁
Demo2.readMethod();
}
});
thread.start();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 当次访问读锁
Demo2.readMethod();
}
});
thread2.start();
Thread.sleep(20000);
System.out.println("result:" + count);
}
}
预计得值:result:-10000
实际得值:result:-9999(小于等于10000,如果等于10000,多重试几次。)
发现:并没有加锁效果,读锁是共享的(非互斥)
当次两个线程都使用 写锁(代码基本没变,就变更了一下访问的方法)
public class Demo2 {
//共享变量
static int count = 0;
// 重入读写锁
static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
// 写锁
static Lock write = rwl.writeLock();
// 读锁
static Lock read = rwl.readLock();
//当前方法使用读锁
public static void readMethod() {
read.lock(); //读锁
try {
// 为了展示出多线程同时操作同一数据会出现问题。如果去掉之后可能会正常计算出数据
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
read.unlock(); //释放读锁
}
}
//当前方法使用读锁
public static void writeMethod() {
write.lock(); //Other
try {
// 为了展示出多线程同时操作同一数据会出现问题。如果去掉之后可能会正常计算出数据
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
write.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 当次访问写锁
Demo2.writeMethod();
}
});
thread.start();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 当次访问写锁
Demo2.writeMethod();
}
});
thread2.start();
Thread.sleep(20000);
System.out.println("result:" + count);
}
}
预计得值:result:10000
实际得值:result:10000(多次重试都是:10000)
发现:有加锁效果,写锁是非共享的(互斥)
当次两个线程一个使用 写锁,另个一使用读锁(代码基本没变,就变更了一下访问的方法)
public class Demo2 {
//共享变量
static int count = 0;
// 重入读写锁
static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
// 写锁
static Lock write = rwl.writeLock();
// 读锁
static Lock read = rwl.readLock();
//当前方法使用读锁
public static void readMethod() {
read.lock(); //读锁
try {
// 为了展示出多线程同时操作同一数据会出现问题。如果去掉之后可能会正常计算出数据
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
read.unlock(); //释放读锁
}
}
//当前方法使用读锁
public static void writeMethod() {
write.lock(); //Other
try {
// 为了展示出多线程同时操作同一数据会出现问题。如果去掉之后可能会正常计算出数据
Thread.sleep(1);
count++;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
write.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 当次访问读锁
Demo2.readMethod();
}
});
thread.start();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
// 当次访问写锁
Demo2.writeMethod();
}
});
thread2.start();
Thread.sleep(20000);
System.out.println("result:" + count);
}
}
预计得值:result:10000
实际得值:result:10000(多次重试都是:10000)
发现:有加锁效果,读锁和写锁 是非共享的(互斥)
总结:
- 读读不互斥
- 写写互斥
- 读写互斥