读写锁小总结

今天小组组织了一次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并行执行的。

 

欢迎拍砖

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值