现在都是“大数据”时代,大量的用户数据需要处理,如何保证大量数据在多线程下的安全,成了比较重要的问题。
今天要学习的就是java.util.concurrent包下Locks接口的一个实现类,ReadWriteLock,读写锁。

读写锁的出现是为了弥补传统同步方式synchronized的缺憾,使用synchronized同步的方法或语句,当多线程读取一个大数据时,每次只能有一个线程读取,其他线程都得等当前线程读取完才能读,太耗时间。
代码如下:
/**

  • 读写锁 : 在读写大数据时有效提高效率
  • 对数据进行读写时,同时读可以不用同步,同时写、同时读写才用
  • @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() {br/>@Override
    public void run() {
    data.setData(new Random().nextInt(30));
    }
    }).start();
    }
    for (int i = 0; i < 3; i++) {
    new Thread(new Runnable() {br/>@Override
    public void run() {
    data.getData();
    }
    }).start();
    }
    }

}

/**

  • 使用synchronized同步的类
  • 当多线程读取一个大数据时,每次只能有一个线程读取,其他线程都得等当前线程读取完才能读,太耗时间
  • @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 + "完毕 <---");
    }

}

为了模拟大数据,我们把每次读取的时间延长一些。

运行结果:

可以看到,不管每个线程读取数据耗时多长,同时只能有一个线程读取数据,其他数据都被阻塞,等待当前线程结束后才能访问。

而使用读写锁后,多个线程同时读取时,可以并发执行,不会阻塞。

代码如下:

/**

  • 读写锁 : 在读写大数据时有效提高效率
  • 对数据进行读写时,同时读可以不用同步,同时写、同时读写才用
  • @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() {br/>@Override
    public void run() {
    data.setData(new Random().nextInt(30));
    }
    }).start();
    }
    for (int i = 0; i < 3; i++) {
    new Thread(new Runnable() {br/>@Override
    public void run() {
    data.getData();
    }
    }).start();
    }
    }

}

/**

  • 使用读写锁同步的类
  • 多个线程同时读取时,可以并发执行,不会阻塞
  • @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,谢谢这位前辈)