当前位置: 首页 > 知识库问答 >
问题:

java多线程理解公平锁

申屠弘图
2023-03-14

我试图理解java中的公平锁,并从中执行了一个实现

http://tutorials.jenkov.com/java-concurrency/starvation-and-fairness.html

哪个很好

代码如下所示

public class FairLock 
{
    private boolean           isLocked       = false;
    private Thread            lockingThread  = null;
    private List<QueueObject> waitingThreads =
            new ArrayList<QueueObject>();

  public void lock() throws InterruptedException
  {
    QueueObject queueObject           = new QueueObject();
    boolean     isLockedForThisThread = true;
    synchronized(this){waitingThreads.add(queueObject);}

    while(isLockedForThisThread)
    {
     synchronized(this)
     {
      isLockedForThisThread =
      isLocked || waitingThreads.get(0) != queueObject;
      if(!isLockedForThisThread)
      {
       isLocked = true;
       waitingThreads.remove(queueObject);
       lockingThread = Thread.currentThread();
       return;
     }
  }

  try{queueObject.doWait();}
  catch(InterruptedException e)
  {
    synchronized(this) { waitingThreads.remove(queueObject); }
    throw e;
  }
}
 }

  public synchronized void unlock()
  {
    if(this.lockingThread != Thread.currentThread())
    {
      throw new IllegalMonitorStateException(
        "Calling thread has not locked this lock");
    }

    isLocked      = false;
    lockingThread = null;

    if(waitingThreads.size() > 0){waitingThreads.get(0).doNotify();}
  }
}

队列对象的代码

public class QueueObject 
{

  private boolean isNotified = false;

  public synchronized void doWait() throws InterruptedException
  {
   while(!isNotified){this.wait();}
   this.isNotified = false;
  }

  public synchronized void doNotify() 
  {
    this.isNotified = true;
    this.notify();
  }

  public boolean equals(Object o){return this == o;}
}

我了解其中的大部分,但我有两个疑问

1)在这一行代码中

   isLockedForThisThread =
   isLocked || waitingThreads.get(0) != queueObject;

这个零件是做什么用的?

waitingThreads.get(0) != queueObject;

它有什么作用?因为我删除了这部分代码,得到了相同的正确结果。

2) 因为我相信我不需要这部分代码,所以我将lock()方法更改为下面给出的版本。

public void myLock() throws InterruptedException
{
    QueueObject queueObject= new QueueObject();
    synchronized(this){waitingThreads.add(queueObject);}

    while(true)
    {
      synchronized(this)
      {
       if(!isLocked)
       {
        isLocked = true;
        waitingThreads.remove(queueObject);
        lockingThread = Thread.currentThread();
        return;
       }
     }

     try{queueObject.doWait();}
     catch(InterruptedException e)
     {
       synchronized(this){waitingThreads.remove(queueObject);}
       throw e;
     }
   }

这也给了我正确的结果,但我相信我还没有研究过所有的案例,在某些情况下,这将失败,我希望基本上能得到专家的意见

.这在哪里起作用?

...它会在哪里失败?

我是新的多线程和基本上寻找一些解释(在第1部分)和反馈(在第2部分)我的问题

非常感谢。

共有1个答案

杨安歌
2023-03-14

注意这一行

synchronized(this){waitingThreads.add(queueObject);}

在这里,我们将新创建的队列对象添加到队列中,但我们是以同步方式进行的,因为可能有两个线程同时尝试将对象添加到列表中。记住这一点,让我们转到下一个同步块

isLockedForThisThread =
  isLocked || waitingThreads.get(0) != queueObject;

现在,如果另一个线程正在运行,那么这个线程将被锁定,理想情况下,它会将isLocked设置为true,所以您的问题是为什么我们也在做waitingThreads。获得(0)!=队列对象。想象一下,在前一个块中,线程A在线程B之前添加了一个对象到队列中,它是自己的,这将优先让A首先运行,现在线程A可能会被挂起,或者什么,线程B首先到达第二个同步块,让我们检查一下现在的情况:1。isLocked为false,因为还没有线程将其设置为true。A是队列中的第一个,然后是B3。线程B正在运行,而线程A挂起

现在,如果你按照你所做的去做,移除| | B的第二部分,你会认为该轮到它来获取锁了,并且会进入下一个“if”语句,这不是正确的行为,因为下面的一行将移除队列的第二个元素(在我们的示例中,它可能是第三个,在其他情况下甚至更多),而不是头要素

waitingThreads.remove(queueObject);

我不是专家的任何手段,但这是我看到的问题,希望我已经帮助它可以是棘手的,清楚地解释多线程的行为只使用文本: P

 类似资料:
  • API文档说明: 这个类的构造函数接受一个可选的公平性参数。当设置为true时,在争用状态下,锁倾向于授予对等待时间最长的线程的访问权限。 注意,锁的公平性并不能保证线程调度的公平性。因此,使用公平锁的许多线程中的一个可以连续多次获得它,而其他活动线程没有进展,并且当前没有持有锁。 我无法理解第2点: 如果一个线程连续多次获得锁,那么根据第1点,其他线程将等待更长时间,这确实意味着它们下次将获得锁

  • 本文向大家介绍Java多线程 线程组原理及实例详解,包括了Java多线程 线程组原理及实例详解的使用技巧和注意事项,需要的朋友参考一下 线程组 线程组可以批量管理线程和线程组对象。 一级关联 例子如下,建立一级关联。 输出结果如下 每隔三秒输出两个线程名称,符合预期。 线程组自动归组属性 输出结果如下 没有指定线程组,则归属到当前线程所属的组。 根线程组 运行结果 当前线程的线程组的父线程组是系统

  • 本文向大家介绍理解python多线程(python多线程简明教程),包括了理解python多线程(python多线程简明教程)的使用技巧和注意事项,需要的朋友参考一下 对于python 多线程的理解,我花了很长时间,搜索的大部份文章都不够通俗易懂。所以,这里力图用简单的例子,让你对多线程有个初步的认识。 单线程   在好些年前的MS-DOS时代,操作系统处理问题都是单任务的,我想做听音乐和看电影两

  • 本文向大家介绍Java多线程并发编程和锁原理解析,包括了Java多线程并发编程和锁原理解析的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了Java多线程并发编程和锁原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.前言   最近项目遇到多线程并发的情景(并发抢单&恢复库存并行),代码在正常情况下运行没有什么问题,在高并发压测

  • 本文向大家介绍详解Java多线程处理List数据,包括了详解Java多线程处理List数据的使用技巧和注意事项,需要的朋友参考一下 实例1: 解决问题:如何让n个线程顺序遍历含有n个元素的List集合 实例2: List多线程并发读取读取现有的list对象 实例3: 多线程分段处理List集合 场景:大数据List集合,需要对List集合中的数据同标准库中数据进行对比,生成新增,更新,取消数据 解

  • 本文向大家介绍Java多线程start()方法原理解析,包括了Java多线程start()方法原理解析的使用技巧和注意事项,需要的朋友参考一下 1、为什么启动线程不用run()方法而是使用start()方法 run()方法只是一个类中的普通方法,调用run方法跟调用普通方法一样 而start()是创建线程等一系列工作,然后自己调用run里面的任务内容。 验证代码: 结果: main Thread-