Почему AQS печатается по-другому

#java #debugging #java-8 #java.util.concurrent

Вопрос:

Когда я исследовал AQS, я обнаружил проблему. Я сделал копию исходного кода aQS и ReentrantLock, добавил печать, а затем написал тестовую программу, которая при правильной работе печаталась только один раз после пробуждения потока. Но когда я добавляю точку останова в метод parkAndCheckInterrupt, я печатаю ее дважды. Почему?

 public static void main(String[] args) {  MyReentrantLock lock = new MyReentrantLock();  Thread thread0 = new Thread(() -gt; {  lock.lock();  try {  Thread.sleep(3000000);  } catch (InterruptedException e) {  e.printStackTrace();  }  lock.unlock();  });  thread0.start();   try {  Thread.sleep(3000);  } catch (InterruptedException e) {  e.printStackTrace();  }  Thread thread1 = new Thread(() -gt; {  lock.lock();  lock.unlock();  });  thread1.start();   Thread thread2 = new Thread(() -gt; {  lock.lock();  lock.unlock();  });  thread2.start();   Thread thread3 = new Thread(() -gt; {  lock.lock();  lock.unlock();  });  thread3.start();   try {  Thread.sleep(2000);  } catch (InterruptedException e) {  e.printStackTrace();  }  thread2.interrupt();  }   final boolean acquireQueued(final MyAbstractQueuedSynchronizer.Node node, int arg) {  boolean failed = true;  try {  boolean interrupted = false;  for (;;) {  final MyAbstractQueuedSynchronizer.Node p = node.predecessor();  System.out.println(Thread.currentThread().getName()   "-gt; Spin get lock---------");**//Printed content**  if (p == head amp;amp; tryAcquire(arg)) {  setHead(node);  p.next = null; // help GC  failed = false;  return interrupted;  }  if (shouldParkAfterFailedAcquire(p, node) amp;amp;  parkAndCheckInterrupt())  interrupted = true;  }  } finally {  if (failed)  cancelAcquire(node);  }  }   private final boolean parkAndCheckInterrupt() {  LockSupport.park(this);  return Thread.interrupted();**//Add a breakpoint**  }  

Ниже приведен результат обычного запуска и точки останова

 normal Thread-1-gt; Spin get lock--------- Thread-1-gt; Spin get lock--------- Thread-2-gt; Spin get lock--------- Thread-2-gt; Spin get lock--------- Thread-3-gt; Spin get lock--------- Thread-3-gt; Spin get lock--------- Thread-2-gt; Spin get lock---------  breakpoint Thread-1-gt; Spin get lock--------- Thread-1-gt; Spin get lock--------- Thread-2-gt; Spin get lock--------- Thread-2-gt; Spin get lock--------- Thread-3-gt; Spin get lock--------- Thread-3-gt; Spin get lock--------- Thread-2-gt; Spin get lock--------- Thread-2-gt; Spin get lock---------  

Комментарии:

1. Где твое MyReentrantLock и MyAbstractQueuedSynchronizer

2. Я сделал полную копию исходного кода AQS и ReentrantLock. Цель состоит в том, чтобы иметь возможность добавить немного печати в код для удобства отладки. В противном случае, точно так же, как исходный код.

3. Здравствуйте, я тоже китаец, могу я добавить ваш чат в wechat?

4. Я воспроизвел то, что вы сказали. Я потрачу некоторое время, чтобы взглянуть на него и ответить вам позже.

5. Хорошо, спасибо. Сначала я заподозрил, что Park и Unpark имеют какое-то отношение к отладке, поэтому я просмотрел исходный код JVM для Park и Unpark, но не нашел ничего ценного. Но я думаю, что это как-то связано с механизмом отладки IDEA.