了解Java multhreading中的公平锁

时间:2019-04-29 17:31:13

标签: java multithreading

我试图了解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 个答案:

答案 0 :(得分:2)

注意此行

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

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

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

现在,如果正在运行其他线程(最好将isLocked设置为true),则该线程将被锁定,因此您的问题是为什么我们还要执行waitingThreads.get(0)!= queueObject。想象一下,在前一个块中,线程A在线程B之前将对象添加到队列中,它是拥有的,这将赋予A首先运行的优先级,现在线程A可能挂起或某些东西,线程B首先到达第二个同步块,让我们检查一下我们现在拥有的: 1. isLocked为false,因为还没有线程将其设置为true 2. A在队列中排在首位,然后是B 3.在线程A挂起的同时线程B正在运行

现在,如果您执行了操作,则删除了||的第二部分。 B将认为轮到该锁定并进入下一个'if'语句,这不是正确的行为,因为下一行将删除队列的第二个元素(在我们的示例中,它可能是在其他情况下为3甚至更高),而不是head元素。

waitingThreads.remove(queueObject);

我绝对不是专家,但这是我看到的问题,希望我能帮助仅使用文本来清楚地解释多线程行为可能很棘手。