#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.