Ref:

  • https://stackoverflow.com/a/56659651/8945448
  • https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/LockSupport.html

    Synchronized 实现阻塞等待

    1. @Test
    2. public void test_objWaitNotify() throws InterruptedException {
    3. Object lock = new Object();
    4. Runnable task1 = () -> {
    5. synchronized (lock) {
    6. System.out.printf("%s get lock. %n", Thread.currentThread().getName());
    7. try {
    8. // release lock
    9. lock.wait();
    10. System.out.printf("%s get resumed. %n", Thread.currentThread().getName());
    11. } catch (InterruptedException e) {
    12. e.printStackTrace();
    13. }
    14. }
    15. };
    16. Thread thread1 = new Thread(task1);
    17. thread1.setName("Thread1");
    18. thread1.start();
    19. Runnable task2 = () -> {
    20. synchronized (lock) {
    21. System.out.printf("%s get lock. %n", Thread.currentThread().getName());
    22. lock.notify();
    23. try {
    24. System.out.printf("%s notify other threads. %n", Thread.currentThread().getName());
    25. TimeUnit.SECONDS.sleep(1);
    26. } catch (InterruptedException e) {
    27. e.printStackTrace();
    28. }
    29. System.out.printf("%s synchronized() done and release lock. %n", Thread.currentThread().getName());
    30. }
    31. };
    32. Thread thread2 = new Thread(task2);
    33. thread2.setName("Thread2");
    34. thread2.start();
    35. // block main thread waiting for sub-threads
    36. TimeUnit.SECONDS.sleep(1);
    37. }

    LockSupport.park()

    park() method:
    Disables the current thread for thread scheduling purposes unless the permit is available.

    1. /**
    2. * Disables the current thread for thread scheduling purposes unless the
    3. * permit is available.
    4. *
    5. * <p>If the permit is available then it is consumed and the call returns
    6. * immediately; otherwise
    7. * the current thread becomes disabled for thread scheduling
    8. * purposes and lies dormant until one of three things happens:
    9. *
    10. * <ul>
    11. * <li>Some other thread invokes {@link #unpark unpark} with the
    12. * current thread as the target; or
    13. *
    14. * <li>Some other thread {@linkplain Thread#interrupt interrupts}
    15. * the current thread; or
    16. *
    17. * <li>The call spuriously (that is, for no reason) returns.
    18. * </ul>
    19. *
    20. * <p>This method does <em>not</em> report which of these caused the
    21. * method to return. Callers should re-check the conditions which caused
    22. * the thread to park in the first place. Callers may also determine,
    23. * for example, the interrupt status of the thread upon return.
    24. *
    25. * @param blocker the synchronization object responsible for this
    26. * thread parking
    27. * @since 1.6
    28. */
    29. public static void park(Object blocker) {
    30. Thread t = Thread.currentThread();
    31. setBlocker(t, blocker);
    32. UNSAFE.park(false, 0L);
    33. setBlocker(t, null);
    34. }

    自定义队列锁:

    1. class FIFOMutex {
    2. private final AtomicBoolean locked = new AtomicBoolean(false);
    3. private final Queue<Thread> waiters
    4. = new ConcurrentLinkedQueue<Thread>();
    5. public void lock() {
    6. boolean wasInterrupted = false;
    7. Thread current = Thread.currentThread();
    8. waiters.add(current);
    9. // Block while not first in queue or cannot acquire lock
    10. while (waiters.peek() != current ||
    11. !locked.compareAndSet(false, true)) {
    12. LockSupport.park(this);
    13. if (Thread.interrupted()) // ignore interrupts while waiting
    14. wasInterrupted = true;
    15. }
    16. waiters.remove();
    17. if (wasInterrupted) // reassert interrupt status on exit
    18. current.interrupt();
    19. }
    20. public void unlock() {
    21. locked.set(false);
    22. LockSupport.unpark(waiters.peek());
    23. }
    24. }