现在都是“大数据”时代,大量的用户数据需要处理,如何保证大量数据在多线程下的安全,成了比较重要的问题。
今天要学习的就是java.util.concurrent包下Locks接口的一个实现类,ReadWriteLock,读写锁。
读写锁的出现是为了弥补传统同步方式synchronized的缺憾,使用synchronized同步的方法或语句,当多线程读取一个大数据时,每次只能有一个线程读取,其他线程都得等当前线程读取完才能读,太耗时间。
代码如下:
/**
* 读写锁 : 在读写大数据时有效提高效率<br>
* 对数据进行读写时,同时读可以不用同步,同时写、同时读写才用
* @author sxzhang
* @since 2015/8/21 9:23
*
*/
public class ReadWriteTest {
public static void main(String[] args) {
final Data data = new Data();
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
data.setData(new Random().nextInt(30));
}
}).start();
}
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
data.getData();
}
}).start();
}
}
}
/**
* 使用synchronized同步的类<br>
* 当多线程读取一个大数据时,每次只能有一个线程读取,其他线程都得等当前线程读取完才能读,太耗时间
* @author sxzhang
*
*/
class Data{
private int data; //共享资源
public synchronized void setData(int data) {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + "准备写数据:--->");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.data = data;
System.out.println(threadName + "写入 " + this.data + "完毕 --->");
}
public synchronized void getData() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + "准备读取数据:<---");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + "读取数据 " + this.data + "完毕 <---");
}
}
</pre><span style="font-size:18px">为了模拟大数据,我们把每次读取的时间延长一些。</span><p></p><p><span style="font-size:18px">运行结果:</span></p><p><img src="https://img-blog.csdn.net/20150821100455408?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /></p><p><span style="font-size:18px">可以看到,不管每个线程读取数据耗时多长,同时只能有一个线程读取数据,其他数据都被阻塞,等待当前线程结束后才能访问。</span></p><p><span style="font-size:18px"></span></p><p><span style="font-size:18px">而使用读写锁后,多个线程同时读取时,可以并发执行,不会阻塞。</span></p><p><span style="font-size:18px">代码如下:</span></p><p></p><pre name="code" class="java">/**
* 读写锁 : 在读写大数据时有效提高效率<br>
* 对数据进行读写时,同时读可以不用同步,同时写、同时读写才用
* @author sxzhang
* @since 2015/8/21 9:23
*
*/
public class ReadWriteTest {
public static void main(String[] args) {
final Data1 data = new Data1();
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
data.setData(new Random().nextInt(30));
}
}).start();
}
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
data.getData();
}
}).start();
}
}
}
/**
* 使用读写锁同步的类<br>
* 多个线程同时读取时,可以并发执行,不会阻塞
* @author sxzhang
*
*/
class Data1{
private int data; //共享资源
//Creates a new ReentrantReadWriteLock with default (nonfair) ordering properties.
//默认不公平,指的是,阻塞时间长的线程不一定先获取被释放的资源
private ReadWriteLock rwl = new ReentrantReadWriteLock();
public void setData(int data) {
rwl.writeLock().lock(); //記得用完及時釋放锁
try{
String threadName = Thread.currentThread().getName();
System.out.println(threadName + "准备写数据:--->");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.data = data;
System.out.println(threadName + "写入 " + this.data + "完毕 --->");
}finally{
rwl.writeLock().unlock(); //release the writeLock
}
}
public void getData() {
rwl.readLock().lock();
try{
String threadName = Thread.currentThread().getName();
System.out.println(threadName + "准备读取数据:<---");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + "读取数据 " + this.data + "完毕 <---");
}finally{
rwl.readLock().unlock();
}
}
}
运行结果:
可以看到,线程3、4、5同时读取数据,这样就比synchronized节省不少时间。
要学习java并发编程,java.util.concurrent包下的内容还要好好学习
(学习参考自http://blog.csdn.net/ghsau/article/details/7461369/#comments,谢谢这位前辈)