Java并发编程 - ABAB问题的实现
其实学到了并发这块和底层操作系统是紧密联系的,所以操作系统对进程的处理方式在Java中也是一样的,这篇我们不讲解并发的详细知识,先实现一道经典的并发问题,让读者自己体会并发编程之美。
synchronized的解决方案
-
实现如下,读者可以调整线程A,B中的wait和notify出现的位置,会发现有些会造成死锁。
public class SyncABABSolution { public static void main(String[] args) { Thread thread1 = new Thread(() -> { synchronized (args) { try { for (; ; ) { args.wait(); System.out.println("A"); TimeUnit.SECONDS.sleep(1); args.notify(); } } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread thread2 = new Thread(() -> { synchronized (args) { try { for (; ; ) { args.notify(); args.wait(); System.out.println("B"); TimeUnit.SECONDS.sleep(1); } } catch (InterruptedException e) { e.printStackTrace(); } } }); thread1.start(); thread2.start(); } }
Lock的解决方案
-
实现如下,这里用到了juc包下面的Lock和Condition类。
public class LockABABSolution { private static final Lock lock = new ReentrantLock(); private static final Condition condition = lock.newCondition(); public static void main(String[] args) { Thread thread1 = new Thread(() -> { lock.lock(); try { for (; ; ) { condition.await(); System.out.println("A"); TimeUnit.SECONDS.sleep(1); condition.signal(); } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } }); Thread thread2 = new Thread(() -> { lock.lock(); try { for (; ; ) { condition.signal(); condition.await(); System.out.println("B"); TimeUnit.SECONDS.sleep(1); } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } }); thread1.start(); thread2.start(); } }
总结
我们可以看到,最直观的不同是synchronized是关键字,而Lock是一个类。这个其实可以理解为synchronized是基于jvm层面的控制,而Lock锁是api层面的控制。