并发编程经典面试题,多个线程并发执行,按顺序交替打印123,或abc
java实现方式
- ReentrantLock + Condition 可重入锁 + 条件信号量
- sychronize 加锁
- 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();
}
}