`

java 读写锁详解

阅读更多

详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt124

 

在java多线程中,为了提高效率有些共享资源允许同时进行多个读的操作,但只允许一个写的操作,比如一个文件,只要其内容不变可以让多个线程同时读,不必做排他的锁定,排他的锁定只有在写的时候需要,以保证别的线程不会看到数据不完整的文件。

   下面是个关于多线程读写锁的例子,我稍微做了下修改,蛮容易理解的,来至于http://www.highya.com/redirect.php?fid=113&tid=7180&goto=nextoldset

这里模拟了这样一个场景: 在ReadWriteLockOperator对象里设置一个共享资源 shareResources 。
有3个读者(A, B, C)一直连续的从 shareResources 获取信息, 然后输出到控制台 ;有一个作者每隔60秒往shareResources 加入信息, 加信息的过程相对耗时, 在这段时间, 任何读者都不能访问 shareResources。
  写了4个类来验证这种情况,只在windows下做了测试。
  ReadTask.java       读任务
  WriteTask.java      写任务
  ReadWriteLockLogic.java     读写操作的逻辑
  ReadWriteLockTest.java      带有main方法的测试类

---------------------------------------混哥线-----------------------------------------------    

public class ReadTask extends Thread {
  //logic bean
  private ReadWriteLockLogic readWriteLockOperator;

  //读者
  private String reader;
  public ReadTask(ReadWriteLockLogic readWriteLockOperator, String reader) {
    this.readWriteLockOperator = readWriteLockOperator;
    this.reader = reader;
  }

  private ReadTask(){}
  // 执行任务
  public void run() {
    if(this.readWriteLockOperator != null){
      try {
        while(!isInterrupted()){
          Thread.sleep(200);
          System.out.println(reader + " read:" + Thread.currentThread().toString() + " : " + this.readWriteLockOperator.read());
        }
      } catch (Exception e) {
        // TODO: handle exception
      }
    }
  }
}

-------------------------------------------------------------------------------------

public class WriteTask  extends Thread{
  //logic bean
  private ReadWriteLockLogic readWriteLockOperator;

  //作者
  private String writer;

  public WriteTask(ReadWriteLockLogic readWriteLockOperator, String writer) {
    this.readWriteLockOperator = readWriteLockOperator;
    this.writer = writer;
  }

  private WriteTask(){}
  // 一个很耗时的写任务
  public void run() {
    try {
      while(!isInterrupted()){
        Thread.sleep(100);
        this.readWriteLockOperator.write(this.writer, "hehehhe");
      }
    } catch (Exception e) {
      // TODO: handle exception
    }
  }
}

----------------------------------------------------------------------------------

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
//读写操作的逻辑
public class ReadWriteLockLogic {
  // 初始化一个 ReadWriteLock
  private ReadWriteLock lock = new ReentrantReadWriteLock();

  //共享资源
  private List<String> shareResources = new ArrayList<String>(0);

  //读
  public String read() {
    // 得到 readLock 并锁定
    Lock readLock = lock.readLock();
    readLock.lock();
    try {
      // 读相对省时,做空循环 大约0.5second
      for(int i=0 ;i<2500000; i++){
        System.out.print("");
      }
      // 做读的工作
      StringBuffer buffer = new StringBuffer();
      for (String shareResource : shareResources) {
        buffer.append(shareResource);
        buffer.append("\t");      
      }
      return buffer.toString();
    } finally {
      readLock.unlock();//一定要保证锁的释放
    }
  }
  //写
  public void write(String writer, String content) {
    // 得到 writeLock 并锁定
    Lock writeLock = lock.writeLock();
    writeLock.lock();
    try {
      System.out.println(writer + " write ===" + Thread.currentThread().toString());
      // 写比较费时,所以做空循环 大约13second
      for(int i=0 ;i<10000000; i++){
        System.out.print("");
        System.out.print("");
      }
    
      // 做写的工作
      int count = shareResources.size();
      for (int i=count; i < count + 1; i++) {
        shareResources.add(content + "_" + i);
      }
    } finally {
      writeLock.unlock();//一定要保证锁的释放
    }
  }
}
------------------------------------------------------------------------------------

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ReadWriteLockTest {
  public static void main(String[] args) throws InterruptedException, ExecutionException {
    //1 创建一个具有排程功能的线程池
    ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
    //2 读写锁的logic bean
    ReadWriteLockLogic lockOperator = new ReadWriteLockLogic();
    //3 生成一个可执行任务(该任务执行完毕可以返回结果 或者 抛出异常;而Runnable接口的run方法则不行)
    Runnable writeTask1 = new WriteTask(lockOperator, "作者A");
    //4 延时0秒后每2秒重复执行writeTask1;
    service.scheduleAtFixedRate(writeTask1, 0, 60, TimeUnit.SECONDS);
    //5 创建3个读任务
    Runnable readTask1 = new WriteTask(lockOperator, "作者B");
    Runnable readTask2 = new ReadTask(lockOperator, "读者B");
    Runnable readTask3 = new ReadTask(lockOperator, "读者C");
    //6 延时0秒后每秒执行一次task1;
    service.scheduleAtFixedRate(readTask1, 1, 1, TimeUnit.SECONDS);
    service.scheduleAtFixedRate(readTask2, 2, 1, TimeUnit.SECONDS);
    service.scheduleAtFixedRate(readTask3, 3, 1, TimeUnit.SECONDS);
  
  }
}

----------------------------------------------------------------------------------------

作者A write ===Thread[pool-1-thread-1,5,main]
作者B write ===Thread[pool-1-thread-4,5,main]
读者C read:Thread[pool-1-thread-3,5,main] : hehehhe_0 hehehhe_1 
读者B read:Thread[pool-1-thread-2,5,main] : hehehhe_0 hehehhe_1

作者A write ===Thread[pool-1-thread-1,5,main]

................

通过观察控制台,可以看到作者a出现后,大约5秒作者b才会出现,而又过了5秒后,读者c和读者b同时会出现,接着5秒后,作者a又出现了。这说明了,读锁之间没有排斥,可以多线程持有并且排斥WriteLock的持有线程。而WriteLock是全部排斥的,是独占的,比较独!

 

下面是附赠的读写锁的小知识,来至http://www.txdnet.cn/essay/view.jsp?tid=1288670091703&cid=2

(a).重入方面其内部的WriteLock可以获取ReadLock,但是反过来ReadLock想要获得WriteLock则永远都不要想.

(b).WriteLock可以降级为ReadLock,顺序是:先获得WriteLock再获得ReadLock,然后释放WriteLock,这时候线程将保持Readlock的持有.反过来ReadLock想要升级为WriteLock则不可能,为什么?参看(a),呵呵.

(c).ReadLock可以被多个线程持有并且在作用时排斥任何的WriteLock,而WriteLock则是完全的互斥.这一特性最为重要,因为对于高读取频率而相对较低写入的数据结构,使用此类锁同步机制则可以提高并发量.

(d).不管是ReadLock还是WriteLock都支持Interrupt,语义与ReentrantLock一致.

(e).WriteLock支持Condition并且与ReentrantLock语义一致,而ReadLock则不能使用Condition,否则抛出UnsupportedOperationException异常.

分享到:
评论

相关推荐

    java 读写锁代码

    下面我们将详细探讨Java读写锁的概念、实现原理以及如何在实际代码中应用。 1. **读写锁概念**: - 读写锁分为读锁(共享锁)和写锁(独占锁)。读锁允许多个线程同时读取数据,而写锁只允许一个线程进行写操作。 ...

    Java编程读写锁详解

    Java编程读写锁详解 Java编程读写锁是Java并发编程中的一种重要机制,用于解决多线程访问同一个资源时的安全问题。在Java中,读写锁是通过ReadWriteLock接口实现的,该接口提供了readLock和writeLock两种锁的操作...

    08、读写锁ReentrantReadWriteLock&StampLock详解-ev

    读写锁ReentrantReadWriteLock&StampLock详解_e读写锁ReentrantReadWriteLock&StampLock详解_e读写锁ReentrantReadWriteLock&StampLock详解_e读写锁ReentrantReadWriteLock&StampLock详解_e读写锁...

    Java2编程详解.rar

    8. **输入/输出流**:Java的IO流系统支持对文件、网络和其他数据源的读写操作,包括字节流、字符流、对象流等。 9. **多线程**:Java提供了内置的多线程支持,通过Thread类和Runnable接口实现并发执行,理解和掌握...

    Java2编程详解

    5. **输入/输出流**:Java的I/O流系统支持文件读写、网络通信等多种数据传输方式,书中会介绍InputStream、OutputStream、Reader、Writer以及NIO(非阻塞I/O)的相关知识。 6. **多线程**:Java2对多线程编程的支持...

    java读写properties配置文件

    ### Java读写Properties配置文件详解 #### 一、引言 在Java开发中,`Properties`类被广泛用于处理各种类型的配置文件。这些文件通常包含了应用程序运行时所需的配置信息,如数据库连接信息、系统参数等。`...

    8、读写锁ReentrantReadWriteLock&StampLock详解.pdf

    根据提供的文件信息,本文将详细解析读写锁`ReentrantReadWriteLock`以及`StampLock`在Java并发编程中的应用场景及其实现原理。 ### 一、读写锁介绍 #### 1.1 读写锁的基本概念 读写锁是一种特殊的锁机制,它可以...

    java2编程详解(special_edition_using_java)4.rar

    《Java2编程详解》是一本专门针对Java编程技术的深入解析书籍,Special Edition Using Java的第四版,旨在为读者提供全面、深入的Java学习资源。这本书涵盖了从基础语法到高级特性的广泛内容,适合初学者和有经验的...

    java读写xml文件

    ### Java读写XML文件知识点详解 #### 一、概述 在Java编程中,对XML文件进行读取与写入是一项非常常见的任务。XML(可扩展标记语言)是一种用于标记数据的语言,非常适合用来存储和传输数据。Java提供了多种API来...

    java锁机制详解.pdf

    - **ReadWriteLock**:读写锁,允许多个读取线程同时访问,但在写操作时会阻止所有读写线程,提高了读操作的并发性能。 6. **死锁**:当两个或更多线程相互等待对方释放资源,导致无法继续执行的状态。避免死锁的...

    Java内存模型详解

    ### Java内存模型详解 #### 1. JMM简介 ##### i. 内存模型概述 Java内存模型(Java Memory Model, JMM)是Java虚拟机(JVM)的一部分,用于规定程序中的各种变量(包括实例字段、静态字段和数组元素等)在多个...

    Java应用开发详解

    本教程“Java应用开发详解”旨在为初学者提供全面的Java知识体系,覆盖了多线程、集合类、输入/输出(IO)、图形用户界面(GUI)、网络编程、异常处理、数组操作以及位运算等多个核心概念。 1. **多线程**:Java...

    java多线程-读写锁原理

    在Java多线程编程中,读写锁是一种高级的同步机制,它允许多个线程同时读取共享资源,但只允许一个线程写入。这种锁的引入提高了并发性能,特别是在读操作远多于写操作的场景下。Java 5开始,`java.util.concurrent....

    Java_读写json格式的文件方法详解

    Java 读写 JSON 格式的文件方法详解 本文主要讲解了如何在 Java 中读写 JSON 格式的文件,解决了在实际应用中常见的问题。首先,需要了解什么是 JSON 格式,JSON 格式是一种轻量级的数据交换格式,易于人类阅读和...

    java web开发详解源代码

    在这个“Java Web开发详解源代码”中,我们可以深入理解这一领域的核心概念和实践技巧。源代码通常提供了学习和理解这些概念的直观途径,通过分析和运行代码,开发者可以更好地掌握Java Web开发的精髓。 首先,Java...

    Java集合框架详解

    由于使用了哈希表的存储方式,HashMap通常能够提供较快的读写性能。它的遍历顺序是不确定的,且不保证线程安全。可以存储键为null的记录一条,以及值为null的记录多条。当需要线程安全的HashMap时,可以通过...

    java串口通信详解

    本文将深入探讨Java中的串口通信,包括基本概念、使用Java进行串口编程的关键技术和实践示例。 一、串口通信基础 串口通信是指数据以串行方式逐位传输,与并行通信相比,它需要较少的信号线,因此成本更低,适合远...

    Java教程之javaIO详解

    Java IO 详解 Java IO(Input/Output)是 Java 语言中用于处理输入输出操作的类库,提供了大量的类和方法来实现文件、网络、字节流等方面的输入输出操作。下面对 Java IO 中的重要知识点进行详细说明。 一、File ...

Global site tag (gtag.js) - Google Analytics