欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

读写锁小总结

程序员文章站 2024-01-07 08:29:46
...

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

 

欢迎拍砖

相关标签: ReadWriteLock

上一篇:

下一篇: