Ref:
- https://stackoverflow.com/a/56659651/8945448
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/LockSupport.html
Synchronized 实现阻塞等待
@Testpublic void test_objWaitNotify() throws InterruptedException {Object lock = new Object();Runnable task1 = () -> {synchronized (lock) {System.out.printf("%s get lock. %n", Thread.currentThread().getName());try {// release locklock.wait();System.out.printf("%s get resumed. %n", Thread.currentThread().getName());} catch (InterruptedException e) {e.printStackTrace();}}};Thread thread1 = new Thread(task1);thread1.setName("Thread1");thread1.start();Runnable task2 = () -> {synchronized (lock) {System.out.printf("%s get lock. %n", Thread.currentThread().getName());lock.notify();try {System.out.printf("%s notify other threads. %n", Thread.currentThread().getName());TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.printf("%s synchronized() done and release lock. %n", Thread.currentThread().getName());}};Thread thread2 = new Thread(task2);thread2.setName("Thread2");thread2.start();// block main thread waiting for sub-threadsTimeUnit.SECONDS.sleep(1);}
LockSupport.park()
park() method:
Disables the current thread for thread scheduling purposes unless the permit is available./*** Disables the current thread for thread scheduling purposes unless the* permit is available.** <p>If the permit is available then it is consumed and the call returns* immediately; otherwise* the current thread becomes disabled for thread scheduling* purposes and lies dormant until one of three things happens:** <ul>* <li>Some other thread invokes {@link #unpark unpark} with the* current thread as the target; or** <li>Some other thread {@linkplain Thread#interrupt interrupts}* the current thread; or** <li>The call spuriously (that is, for no reason) returns.* </ul>** <p>This method does <em>not</em> report which of these caused the* method to return. Callers should re-check the conditions which caused* the thread to park in the first place. Callers may also determine,* for example, the interrupt status of the thread upon return.** @param blocker the synchronization object responsible for this* thread parking* @since 1.6*/public static void park(Object blocker) {Thread t = Thread.currentThread();setBlocker(t, blocker);UNSAFE.park(false, 0L);setBlocker(t, null);}
自定义队列锁:
class FIFOMutex {private final AtomicBoolean locked = new AtomicBoolean(false);private final Queue<Thread> waiters= new ConcurrentLinkedQueue<Thread>();public void lock() {boolean wasInterrupted = false;Thread current = Thread.currentThread();waiters.add(current);// Block while not first in queue or cannot acquire lockwhile (waiters.peek() != current ||!locked.compareAndSet(false, true)) {LockSupport.park(this);if (Thread.interrupted()) // ignore interrupts while waitingwasInterrupted = true;}waiters.remove();if (wasInterrupted) // reassert interrupt status on exitcurrent.interrupt();}public void unlock() {locked.set(false);LockSupport.unpark(waiters.peek());}}
