文章目录
- 一、标志变量 + 互斥锁
- 二、标志变量 + synchronized
- 三、标志变量 + 互斥锁 + 条件变量
- 四、原子变量
- 五、信号量
一、标志变量 + 互斥锁
标志变量用于标识当前应该是哪个线程进行输出,互斥锁用于保证对标志变量的互斥访问。
public class Main {private static int currentThread = 0; // 标志变量private static final Lock lock = new ReentrantLock(); // 互斥锁public static void main(String[] args) {Thread threadA = new Thread(() -> print("A", 0));Thread threadB = new Thread(() -> print("B", 1));Thread threadC = new Thread(() -> print("C", 2));threadA.start();threadB.start();threadC.start();}private static void print(String message, int threadId) {try {for (int i = 0; i < 10; i++) {lock.lock();while (threadId != currentThread) {lock.unlock();Thread.sleep(1); // 让权等待,非必需lock.lock();}System.out.print(message);currentThread = (currentThread + 1) % 3;lock.unlock();}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}
}
二、标志变量 + synchronized
通过在非静态方法以当前类作为锁可以避免显式的锁定义。
public class Main {public static void main(String[] args) {Print print = new Print();Thread threadA = new Thread(() -> print.loopPrint("A", 0));Thread threadB = new Thread(() -> print.loopPrint("B", 1));Thread threadC = new Thread(() -> print.loopPrint("C", 2));threadA.start();threadB.start();threadC.start();}
}
public class Print {private int currentThread = 0; // 标志变量public void loopPrint(String message, int threadId) {try {for (int i = 0; i < 10; i++) {synchronized (this) {while (threadId != currentThread) {this.wait();}System.out.print(message);currentThread = (currentThread + 1) % 3;this.notifyAll();}}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}
}
三、标志变量 + 互斥锁 + 条件变量
public class Main {private static int currentThread = 0; // 标志变量private static final Lock lock = new ReentrantLock(); // 互斥锁private static final Condition condition = lock.newCondition(); // 条件变量public static void main(String[] args) {Thread threadA = new Thread(() -> print("A", 0));Thread threadB = new Thread(() -> print("B", 1));Thread threadC = new Thread(() -> print("C", 2));threadA.start();threadB.start();threadC.start();}private static void print(String message, int threadId) {try {for (int i = 0; i < 10; i++) {lock.lock();while (threadId != currentThread) {condition.await();}System.out.print(message);currentThread = (currentThread + 1) % 3;condition.signalAll();lock.unlock();}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}
}
四、原子变量
AtomicInteger 通过 CAS、volatile
和 native
方法保证了原子操作,同时避免了 synchronized
的高开销。
public class Main {private static final AtomicInteger currentThread = new AtomicInteger(0); // 原子变量public static void main(String[] args) {Thread threadA = new Thread(() -> print("A", 0));Thread threadB = new Thread(() -> print("B", 1));Thread threadC = new Thread(() -> print("C", 2));threadA.start();threadB.start();threadC.start();}private static void print(String message, int threadId) {for (int i = 0; i < 10; i++) {while (threadId != currentThread.get()) {Thread.yield(); // 让权等待}System.out.print(message);currentThread.set((currentThread.get() + 1) % 3);}}
}
五、信号量
public class Main {private static final Semaphore semaphoreA = new Semaphore(1);private static final Semaphore semaphoreB = new Semaphore(0);private static final Semaphore semaphoreC = new Semaphore(0);public static void main(String[] args) {Thread threadA = new Thread(() -> print("A", semaphoreA, semaphoreB));Thread threadB = new Thread(() -> print("B", semaphoreB, semaphoreC));Thread threadC = new Thread(() -> print("C", semaphoreC, semaphoreA));threadA.start();threadB.start();threadC.start();}private static void print(String message, Semaphore currentSemaphore, Semaphore nextSemaphore) {for (int i = 0; i < 10; i++) {try {currentSemaphore.acquire();System.out.print(message);nextSemaphore.release();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}
}