大家可能遇到这样的情况:在读写共享数据时,要求写入与写入互斥,读取与写入互斥,而读取和读取不要求互斥。我相信大家都知道需要加锁来实现互斥,但是普通的锁能达到我么的要求吗?我们来看看下面的代码:
package org.iti.thread;
import java.util.Random;
public class ThreadReadWriteLock {
public static void main(String[] args) {
final Data data = new Data();
for (int i = 0; i < 2; i++) {
new Thread(new Runnable() {
public void run() {
for (int j = 0; j < 3; j++) {
data.set(new Random().nextInt(30));
}
}
}).start();
}
for (int i = 0; i < 2; i++) {
new Thread(new Runnable() {
public void run() {
for (int j = 0; j < 3; j++) {
data.get();
}
}
}).start();
}
}
}
class Data {
private int data;// 共享数据
public synchronized void set(int data) {
System.out.println(Thread.currentThread().getName() + "准备写入数据");
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.data = data;
System.out.println(Thread.currentThread().getName() + "写入" + this.data);
}
public synchronized void get() {
System.out.println(Thread.currentThread().getName() + "准备读取数据");
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "读取" + this.data);
}
}
Thread-0准备写入数据
Thread-0写入23
Thread-1准备写入数据
Thread-1写入4
Thread-0准备写入数据
Thread-0写入14
Thread-3准备读取数据
Thread-3读取14
Thread-3准备读取数据
Thread-3读取14
Thread-3准备读取数据
Thread-3读取14
Thread-2准备读取数据
Thread-2读取14
Thread-2准备读取数据
Thread-2读取14
Thread-2准备读取数据
Thread-2读取14
Thread-0准备写入数据
Thread-0写入27
Thread-1准备写入数据
Thread-1写入26
Thread-1准备写入数据
Thread-1写入10
从输出结果可以看出,写入与写入互斥,读取与写入互斥了,但同时读取与读取也互斥了。没有达到我们的要求,下面再看看使用读写锁的实现,对代码稍作修改:
package org.iti.thread;
import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ThreadReadWriteLock {
public static void main(String[] args) {
final Data data = new Data();
for (int i = 0; i < 2; i++) {
new Thread(new Runnable() {
public void run() {
for (int j = 0; j < 3; j++) {
data.set(new Random().nextInt(30));
}
}
}).start();
}
for (int i = 0; i < 2; i++) {
new Thread(new Runnable() {
public void run() {
for (int j = 0; j < 3; j++) {
data.get();
}
}
}).start();
}
}
}
class Data {
private int data;// 共享数据
private ReadWriteLock rwl = new ReentrantReadWriteLock();
public void set(int data) {
rwl.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "准备写入数据");
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.data = data;
System.out.println(Thread.currentThread().getName() + "写入"
+ this.data);
} finally {
rwl.writeLock().unlock();
}
}
public void get() {
rwl.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "准备读取数据");
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "读取"
+ this.data);
} finally {
rwl.readLock().unlock();
}
}
}
Thread-0准备写入数据
Thread-0写入6
Thread-1准备写入数据
Thread-1写入26
Thread-1准备写入数据
Thread-1写入3
Thread-1准备写入数据
Thread-1写入0
Thread-2准备读取数据
Thread-3准备读取数据
Thread-3读取0
Thread-2读取0
Thread-0准备写入数据
Thread-0写入27
Thread-0准备写入数据
Thread-0写入1
Thread-3准备读取数据
Thread-2准备读取数据
Thread-3读取1
Thread-2读取1
Thread-3准备读取数据
Thread-2准备读取数据
Thread-3读取1
Thread-2读取1
成功!