使用信号量同步线程:在 Java 中练习并发 - LeetCode 问题 1115,“交替打印 FooBar”
**并发简介**
在软件开发中,并发允许多个进程或线程同时执行,这通常会缩短执行时间并提高资源利用效率。但是,有效的并发管理对于避免竞争条件、死锁和状态不一致等问题至关重要。这时信号量等同步机制就必不可少了。
**理解信号量**
信号量是一种同步工具,用于控制并发系统中多个线程对公共资源的访问。它的作用类似于计数器,用于控制有多少个线程可以同时访问代码的特定部分。信号量操作包括:
信号量对于管理任务之间的依赖关系或确保程序的某些部分按特定顺序运行特别有用。
**问题描述**
class FooBar {
public void foo() {
for (int i = 0; i < n; i++) {
print("foo");
}
}
public void bar() {
for (int i = 0; i < n; i++) {
print("bar");
}
}
}我们有一个类“FooBar”,它有两个方法,“foo()”和“bar()”。这两个方法分别用于打印“foo”和“bar”。难点在于修改这个类,以便当两个不同的线程执行这两个方法时,输出始终重复“n”次“foobar”。无论调度程序对线程的执行顺序如何,都必须实现这一点。
该问题源自 LeetCode,具体来自问题 1115,“交替打印 FooBar”。
**解决方法**
为了确保正确的执行顺序(“foo”后跟“bar”),我们可以使用信号量来协调线程。下面是我们如何使用信号量修改现有的“FooBar”类以实现所需的行为:
以下是“FooBar”类的修改版本:
class FooBar {
private int n;
private Semaphore semFoo = new Semaphore(1); // Initially, allow foo() to proceed
private Semaphore semBar = new Semaphore(0); // Initially, prevent bar() from proceeding
public FooBar(int n) {
this.n = n;
}
public void foo(Runnable printFoo) throws InterruptedException {
for (int i = 0; i < n; i++) {
semFoo.acquire(); // Wait until it's allowed to proceed
printFoo.run(); // This will print "foo"
semBar.release(); // Allow bar() to proceed
}
}
public void bar(Runnable printBar) throws InterruptedException {
for (int i = 0; i < n; i++) {
semBar.acquire(); // Wait until it's allowed to proceed
printBar.run(); // This will print "bar"
semFoo.release(); // Allow foo() to proceed again
}
}
}**运行代码**
为了演示这个解决方案,我们可以创建一个“FooBar”实例并启动两个线程,每个线程负责以下方法之一:
public class Main {
public static void main(String[] args) {
FooBar fooBar = new FooBar(2); // Example for n = 2
Thread threadA = new Thread(() -> {
try {
fooBar.foo(() -> System.out.print("foo"));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
Thread threadB = new Thread(() -> {
try {
fooBar.bar(() -> System.out.print("bar"));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
threadA.start();
threadB.start();
}
}此设置确保当 n = 2 时,控制台上的输出为“foobarfoobar”,展示了信号量在控制 Java 应用程序中线程执行顺序方面的强大功能。
