面试题:并发编程系列 - 交替打印

113 阅读2分钟

并发编程经典面试题,多个线程并发执行,按顺序交替打印123,或abc

java实现方式

  1. ReentrantLock + Condition 可重入锁 + 条件信号量
  2. sychronize 加锁
  3. Semaphore 同步信号量

ReentrantLock + Condition

Condition await

public class PrintABC {  
  
private static int num = 1;  
  
// 一个锁 + 三个条件信号量  
private static final ReentrantLock lock = new ReentrantLock();  
private static final Condition condition1 = lock.newCondition();  
private static final Condition condition2 = lock.newCondition();  
private static final Condition condition3 = lock.newCondition();  
private static final CountDownLatch latch = new CountDownLatch(3);  
private static final int CYCLE = 10;  
  
private static void printOne() {  
int cnt = CYCLE;  
while(--cnt > 0) {  
lock.lock();  
try {  
while (num != 1) {  
condition1.await();  
}  
System.out.println(num);  
num = 2;  
condition2.signal();  
} catch (Exception e) {  
e.printStackTrace();  
} finally {  
lock.unlock();  
}  
}  
latch.countDown();  
}  
  
private static void printTwo() {  
int cnt = CYCLE;  
while(--cnt > 0) {  
lock.lock();  
try {  
while (num != 2) {  
condition2.await();  
}  
System.out.println(num);  
num = 3;  
// 唤醒3  
condition3.signal();  
} catch (Exception e) {  
Thread.currentThread().interrupt();  
} finally {  
lock.unlock();  
}  
}  
latch.countDown();  
}  
  
private static void printThree() {  
int cnt = CYCLE;  
while(--cnt > 0) {  
lock.lock();  
try {  
while (num != 3) {  
condition3.await();  
}  
System.out.println(num);  
num = 1;  
condition1.signal();  
} catch (Exception e) {  
e.printStackTrace();  
} finally {  
lock.unlock();  
}  
}  
latch.countDown();  
}  
  
public static void main(String[] args) {  
Thread t1 = new Thread(PrintABC::printOne);  
Thread t2 = new Thread(PrintABC::printTwo);  
Thread t3 = new Thread(PrintABC::printThree);  
t1.start();  
t2.start();  
t3.start();  
  
try {  
// 主线程可以确保所有工作线程都完成后再继续执行  
latch.await();  
} catch (Exception e) {  
e.printStackTrace();  
}  
}  
  
}

synchronized

synchronized , wait 和 notifyAll

public class PrintABC2 {  
private static final int cycle = 10;  
private static final Object lock = new Object();  
// 写立即可见  
private static volatile int num = 1;  
private static final CountDownLatch latch = new CountDownLatch(3);  
  
private static void print1() {  
int cnt = cycle;  
while (--cnt > 0) {  
synchronized (lock) {  
while (num != 1) {  
try {  
lock.wait();  
} catch (InterruptedException e) {  
e.printStackTrace();  
}  
}  
System.out.println(num);  
num = 2;  
lock.notifyAll();  
}  
}  
latch.countDown();  
}  
  
private static void print2() {  
int cnt = cycle;  
while (--cnt > 0) {  
synchronized (lock) {  
while (num != 2) {  
try {  
lock.wait();  
} catch (InterruptedException e) {  
e.printStackTrace();  
}  
}  
System.out.println(num);  
num = 3;  
lock.notifyAll();  
}  
}  
latch.countDown();  
}  
  
private static void print3() {  
int cnt = cycle;  
while (--cnt > 0) {  
synchronized (lock) {  
while (num != 3) {  
try {  
lock.wait();  
} catch (InterruptedException e) {  
e.printStackTrace();  
}  
}  
System.out.println(num);  
num = 1;  
lock.notifyAll();  
}  
}  
latch.countDown();  
}  
  
public static void main(String[] args) throws InterruptedException {  
Thread t1 = new Thread(PrintABC2::print1);  
Thread t2 = new Thread(PrintABC2::print2);  
Thread t3 = new Thread(PrintABC2::print3);  
t1.start();  
t2.start();  
t3.start();  
latch.await();  
}  
}

同步信号量

public class PrintABC3 {  
  
private static final Semaphore s1 = new Semaphore(1);  
private static final Semaphore s2 = new Semaphore(0);  
private static final Semaphore s3 = new Semaphore(0);  
private static CountDownLatch latch = new CountDownLatch(3);  
private static final int cycle = 5;  
  
private static void print1() {  
int cnt = cycle;  
while (--cnt > 0) {  
try {  
s1.acquire();  
System.out.println(1);  
s2.release();  
} catch (Exception e) {  
e.printStackTrace();  
}  
}  
latch.countDown();  
}  
private static void print2() {  
int cnt = cycle;  
while (--cnt > 0) {  
try {  
s2.acquire();  
System.out.println(2);  
s3.release();  
} catch (Exception e) {  
e.printStackTrace();  
}  
}  
latch.countDown();  
}  
private static void print3() {  
int cnt = cycle;  
while (--cnt > 0) {  
try {  
s3.acquire();  
System.out.println(3);  
s1.release();  
} catch (Exception e) {  
e.printStackTrace();  
}  
}  
latch.countDown();  
}  
public static void main(String[] args) throws InterruptedException {  
Thread t1 = new Thread(PrintABC3::print1);  
Thread t2 = new Thread(PrintABC3::print2);  
Thread t3 = new Thread(PrintABC3::print3);  
t1.start();  
t2.start();  
t3.start();  
latch.await();  
}  
}