`

读写锁小总结

    博客分类:
  • java
阅读更多

今天小组组织了一次java性能培训,提到了读写锁,以前没有关注过这个东西,于是培训结束后写个程序探索一下读写锁的使用方式。

 

final ReadWriteLock lock = new ReentrantReadWriteLock();

ReadWriteLock具有两把锁,lock.readLock()和lock.writeLock(),特性总结如下:

1、readLock与readLock之间不是互斥的,可以并发执行。实验代码如下:

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Main
{
   public static void main(String[] args)
   {
      final ReadWriteLock lock = new ReentrantReadWriteLock();
      new Thread(new Runnable()
      {

          @Override
          public void run()
          {

              lock.readLock().lock();
              System.out.println(Thread.currentThread().getName() + ":Sleep begin.");
              // 休眠5秒
              sleepInSeconds(5);
              System.out.println(Thread.currentThread().getName()+ ":Sleep complete.");
              lock.readLock().unlock();

           }
       }, "Thread-1").start();

 

      //此处休眠1秒,确保上面的代码得以先执行
      sleepInSeconds(1);

 

      new Thread(new Runnable()
      {

          @Override
          public void run()
         {
             lock.readLock().lock();
             System.out.println(Thread.currentThread().getName()+ ":Sleep begin.");
             // 休眠2秒
             sleepInSeconds(2);
             System.out.println(Thread.currentThread().getName() + ":Sleep complete.");
             lock.readLock().unlock();
        }
     }, "Thread-2").start();
 }

   /**
    * 休眠一定时间,单位5秒
    * @param seconds 要休眠的秒数
    */
    private static void sleepInSeconds(int seconds)
    {
        try
        {
            Thread.sleep(seconds * 1000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
     }

}

Thread-1:Sleep begin.
Thread-2:Sleep begin.
Thread-2:Sleep complete.
Thread-1:Sleep complete.

 

根据输出可以看出,虽然Thread-1已经调用了,lock.readLock().lock(),但是Thread-2还是在Thread-1调用lock.readLock().unlock()之前就执行打印了,说明两个readLock之间是互不影响的。

 

2、readLock和writeLock是互斥的,实验代码如下:

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Main
{
   public static void main(String[] args)
   {
      final ReadWriteLock lock = new ReentrantReadWriteLock();
      new Thread(new Runnable()
      {

          @Override
          public void run()
          {

              lock.readLock().lock();
              System.out.println(Thread.currentThread().getName() + ":Sleep begin.");
              // 休眠5秒
              sleepInSeconds(5);
              System.out.println(Thread.currentThread().getName()+ ":Sleep complete.");
              lock.readLock().unlock();

           }
       }, "Thread-1").start();

 

      //此处休眠1秒,确保上面的代码得以先执行
      sleepInSeconds(1);

 

      new Thread(new Runnable()
      {

          @Override
          public void run()
         {
             lock.writeLock().lock();
             System.out.println(Thread.currentThread().getName()+ ":Sleep begin.");
             // 休眠2秒
             sleepInSeconds(2);
             System.out.println(Thread.currentThread().getName() + ":Sleep complete.");
             lock.writeLock().unlock();
        }
     }, "Thread-2").start();
 }

   /**
    * 休眠一定时间,单位5秒
    * @param seconds 要休眠的秒数
    */
    private static void sleepInSeconds(int seconds)
    {
        try
        {
            Thread.sleep(seconds * 1000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
     }

}

Thread-1:Sleep begin.
Thread-1:Sleep complete.

Thread-2:Sleep begin.
Thread-2:Sleep complete.

 

3、writeLock与writeLock之间是互斥的,实验代码如下

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Main
{
   public static void main(String[] args)
   {
      final ReadWriteLock lock = new ReentrantReadWriteLock();
      new Thread(new Runnable()
      {

          @Override
          public void run()
          {

              lock.writeLock().lock();
              System.out.println(Thread.currentThread().getName() + ":Sleep begin.");
              // 休眠5秒
              sleepInSeconds(5);
              System.out.println(Thread.currentThread().getName()+ ":Sleep complete.");
              lock.writeLock().unlock();

           }
       }, "Thread-1").start();

 

      //此处休眠1秒,确保上面的代码得以先执行
      sleepInSeconds(1);

 

      new Thread(new Runnable()
      {

          @Override
          public void run()
         {
             lock.writeLock().lock();
             System.out.println(Thread.currentThread().getName()+ ":Sleep begin.");
             // 休眠2秒
             sleepInSeconds(2);
             System.out.println(Thread.currentThread().getName() + ":Sleep complete.");
             lock.writeLock().unlock();
        }
     }, "Thread-2").start();
 }

   /**
    * 休眠一定时间,单位5秒
    * @param seconds 要休眠的秒数
    */
    private static void sleepInSeconds(int seconds)
    {
        try
        {
            Thread.sleep(seconds * 1000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
     }

}

Thread-1:Sleep begin.
Thread-1:Sleep complete.

Thread-2:Sleep begin.
Thread-2:Sleep complete.

 

由于readLock与writeLock是互斥的,而readLock与readLock之间是非互斥的,产生了一种猜想,假设有这么一种场景:

Thread-1在第0秒的时候执行了readLock().lock()

Thread-1在第5秒的时候执行了readLock().unlock()

 

Thread-2在第2秒的时候执行了writeLock().lock()

Thread-2在第7秒的时候执行了writeLock().unlock()

 

Thread-3在第4秒的时候执行了writeLock().lock()

Thread-3在第9秒的时候执行了writeLock().unlock()

 

由于Thread-2的writeLock与Thread-1的readLock是互斥的,所以在第5秒之前Thread-2的writeLock之间的代码都不会执行,但Thread-1和Thread-3都是读锁,会不会出现Thread-3的readLock之间的代码先于Thread-2的writeLock之间的代码执行的情况,做个实验便知

 

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Main
{
 private static long beginTime;
 public static void main(String[] args)
 {
  final ReadWriteLock lock = new ReentrantReadWriteLock();
  beginTime = System.currentTimeMillis();
  new Thread(new Runnable()
  {

   @Override
   public void run()
   {
    System.out.println(Thread.currentThread().getName()+ " begin running."+getTime());
    lock.writeLock().lock();
    System.out.println(Thread.currentThread().getName()+ ":Sleep begin."+getTime());
    // 休眠5秒
    sleepInSeconds(5);
    System.out.println(Thread.currentThread().getName()+ ":Sleep complete."+getTime());
    lock.writeLock().unlock();

   }
  }, "Thread-1").start();
  
  //此处休眠1秒,确保上面的代码得以先执行
  sleepInSeconds(2);

  new Thread(new Runnable()
  {

   @Override
   public void run()
   {
    System.out.println(Thread.currentThread().getName()+ " begin running."+getTime());
    lock.writeLock().lock();
    System.out.println(Thread.currentThread().getName()+ ":Sleep begin."+getTime());
    // 休眠2秒
    sleepInSeconds(5);
    System.out.println(Thread.currentThread().getName()+ ":Sleep complete."+getTime());
    lock.writeLock().unlock();
   }
  }, "Thread-2").start();
  
  //此处休眠1秒,确保上面的代码得以先执行
  sleepInSeconds(2);

  new Thread(new Runnable()
  {

   @Override
   public void run()
   {
    System.out.println(Thread.currentThread().getName()+ " begin running."+getTime());
    lock.readLock().lock();
    System.out.println(Thread.currentThread().getName()+ ":Sleep begin."+getTime());
    // 休眠2秒
    sleepInSeconds(5);
    System.out.println(Thread.currentThread().getName()+ ":Sleep complete."+getTime());
    lock.readLock().unlock();
   }
  }, "Thread-3").start();
 }

 /**
  * 休眠一定时间,单位5秒
  * @param seconds 要休眠的秒数
  */
 private static void sleepInSeconds(int seconds)
 {
  try
  {
   Thread.sleep(seconds * 1000);
  }
  catch (InterruptedException e)
  {
   e.printStackTrace();
  }
 }
 
 /**
  * 获取时间字符串
  * @return
  */
 private static String getTime()
 {
  return " Time:"+(System.currentTimeMillis() - beginTime)/1000;
 }

}

Thread-1 begin running. Time:0
Thread-1:Sleep begin. Time:0
Thread-2 begin running. Time:2
Thread-3 begin running. Time:4
Thread-1:Sleep complete. Time:5
Thread-2:Sleep begin. Time:5
Thread-2:Sleep complete. Time:10
Thread-3:Sleep begin. Time:10
Thread-3:Sleep complete. Time:15

 

 

从实验结果来看,Thread-1,Thread-2,Thread-3的代码已经按照原先设计在分别在0秒,2秒,4秒的时刻被调用,但是其lock部分的代码却是:Thread-1的lock代码先执行,Thread-1执行完了才执行Thread-2的lock代码,Thread-2执行完了才执行Thread-3的lock代码。

 

之前猜想的Thread-3的lock代码先于Thread-2的lock代码执行的情况没有出现,也就是说虽然当前正在执行的代码是readLock的代码,但如果存在一个writeLock排队,那么其它readLock是无法与当前正在执行的readLock并行执行的。

 

欢迎拍砖

分享到:
评论

相关推荐

    windows 读写锁 (基于关键区的读写锁类 及自动锁)

    总结,Windows中的读写锁通过合理管理读锁和写锁,实现了高效且公平的线程同步。在实现过程中,要注意避免锁竞争和饥饿问题,并利用自动锁提升代码的可读性和安全性。通过持续优化,可以进一步提高多线程环境下的...

    易语言线程安全之原子锁与读写锁

    总结来说,线程安全是多线程编程的基础,而原子操作和读写锁是实现线程安全的重要工具。易语言提供了丰富的支持,使得开发者能够方便地在自己的程序中实现线程安全,从而构建高效且稳定的多线程应用程序。通过合理...

    读写锁实现例子

    总结起来,这个例子展示了如何使用读写锁来实现线程安全的共享资源访问。通过使用读写锁,我们可以优化多线程程序的性能,尤其是在读操作远多于写操作的场景下。在实际应用中,可以根据系统的需求调整读锁的最大数量...

    C#使用读写锁三行代码简单解决多线程并发的问题

    为了解决这个问题,我们可以利用C#中的读写锁(ReaderWriterLockSlim)来实现线程同步。本文通过三行代码展示了如何使用读写锁解决多线程并发写入文件的冲突。 读写锁的核心在于,它允许多个线程同时读取资源,但只...

    关于读写锁算法的Java实现及思考

    关于读写锁算法的Java实现及思考,是一个深入探讨了多线程环境下资源访问控制机制的主题。在现代软件开发中,尤其是并发编程领域,读写锁(ReadWriteLock)是一种非常重要的同步工具,它允许多个线程同时进行读操作...

    c#多线程读写锁操作

    为了解决这个问题,C#提供了一种名为“读写锁”(ReaderWriterLockSlim)的同步原语,它允许对共享资源进行高效的读写控制,确保了多线程的安全性。本文将深入探讨如何利用读写锁在C#中实现多线程的高效安全资源访问...

    多线程(22)读写锁分离模式1

    总结来说,读写锁分离模式通过分离读锁和写锁,使得在多线程环境下,读操作可以并行执行,写操作保持互斥,从而优化了并发访问的效率。Java的`java.util.concurrent.locks.ReadWriteLock`接口提供了一种标准的实现...

    Java的两种读写锁介绍

    总结,Java中的读写锁为并发编程提供了强大的工具,可以根据具体需求选择合适的锁类型。ReentrantReadWriteLock适合大多数情况,而StampedLock则更适合高并发、对锁有更高级需求的场景。理解并正确使用这些锁机制,...

    行业分类-设备装置-双模式读写锁.zip

    总结来说,双模式读写锁是并发编程中的一种重要工具,它通过区分读写权限,有效提升了多线程环境下的资源利用率和系统性能。理解和正确使用读写锁对于优化并发程序的性能至关重要。在设计和实现并发系统时,应充分...

    易语言源码易语言SRWLock读写锁模块源码.rar

    总结,易语言SRWLock读写锁模块源码的学习,对于提升易语言编程技能,特别是多线程编程的理解,具有重要的实践价值。通过深入研究源码,开发者可以更好地运用这种高级同步机制,解决复杂的并发问题,优化程序性能。

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

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

    python版本的读写锁操作方法

    ### Python版本的读写锁操作方法 #### 一、引言 在多线程编程中,锁是一种常见的同步工具,用于防止多个线程同时访问共享资源导致的数据不一致问题。根据应用场景的不同,锁又可以细分为多种类型,其中读写锁(Read...

    C#解决SQlite并发异常问题的方法(使用读写锁)

    总结来说,文章通过实际案例展示了如何在C#环境下,利用读写锁解决SQLite并发异常问题。通过细致地管理数据库连接和读写锁,可以确保多线程环境下对SQLite数据库的安全访问,从而有效避免并发异常以及数据库损坏的...

    面试官:有没有比读写锁更快的锁?

    总结:面试中,面试官询问是否有比读写锁更快的锁,小明提到了读写锁在读多写少的情况下的优势,但面试官进一步提出了StampedLock。StampedLock通过悲观读、写锁和乐观读模式,提供了一种更高级别的并发控制,特别是...

    在分布式环境中Leader选举互斥锁和读写锁该如何实现

    ### 分布式环境中Leader选举、互斥锁与读写锁的实现 #### 一、Leader选举 在分布式系统中,Leader选举是一种常见的机制,用于在多个节点之间选择一个领导者(Leader)。领导者通常负责协调和管理其他节点的工作。...

    t5557读写软件

    #### 六、总结 T5557读写软件为用户提供了一个方便快捷的方式来管理和操作T5557射频卡。通过精心设计的硬件平台和软件功能,该软件能够满足不同应用场景下的需求。此外,通过定制化的通信协议,保证了数据传输的准确...

    文件读写in C++

    总结来说,C++通过`fstream`库提供了强大的文件操作功能,既可以直接操作基本类型,也可以处理更复杂的数据结构。同时,C语言的FILE*接口也在C++中得到保留,为开发者提供了更多的选择。理解并熟练掌握这些操作,...

    C#多线程读写sqlite

    在C#编程中,多线程技术常用于...总结来说,理解和掌握这些知识点对于在C#中高效且安全地实现多线程读写SQLite数据库至关重要。通过合理利用多线程并正确实施同步策略,可以提高应用程序的并发性能,同时避免数据错误。

    python多线程同步之文件读写控制

    总结来说,Python中的多线程同步在文件读写控制中起到关键作用,防止数据不一致和错误。通过使用`threading.Lock`,我们可以确保在读写文件时只有一个线程在执行,从而保证了数据的正确性和文件操作的顺序。在多线程...

Global site tag (gtag.js) - Google Analytics