- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
出于教育目的,我正在使用多线程实现经典的“嘶嘶声”问题。
“嘶嘶声”游戏是:
The player designated to go first says the number "1", and each player thenceforth counts one number in turn. However, any number divisible by three is replaced by the word fizz and any divisible by five by the word buzz. Numbers divisible by both become fizz buzz
在我的实现中,我有 4 个线程:
我不使用任何锁定和线程同步机制。我的多线程“fizz buzz”实现线程安全吗?如果不是,为什么?我在实现代码中为“可疑”的地方添加了注释。
我的实现:
package threads;
import java.util.function.IntFunction;
public class FizzBuzzGameRunner {
// not volatile
// if other thread updates currentNum and current thread will see old (cached) value
// nothing bad can happen, just burn some CPU cycles uselessly
private int currentNum = 1;
public static void main(String... args) throws InterruptedException {
FizzBuzzGameRunner fizzBuzzGame = new FizzBuzzGameRunner();
startAll(
fizzBuzzGame.createRunnable(n -> (n % 3 != 0 && n % 5 != 0) ? String.valueOf(n) : null),
fizzBuzzGame.createRunnable(n -> (n % 3 == 0 && n % 5 != 0) ? "fizz" : null),
fizzBuzzGame.createRunnable(n -> (n % 3 != 0 && n % 5 == 0) ? "buzz" : null),
fizzBuzzGame.createRunnable(n -> (n % 3 == 0 && n % 5 == 0) ? "fizz buzz" : null)
);
Thread.sleep(1000);
}
private static void startAll(Runnable... workers) {
for (Runnable w : workers) {
Thread t = new Thread(w);
t.setDaemon(true);
t.start();
}
}
private Runnable createRunnable(IntFunction<String> singleStep) {
return () -> {
while (true) {
int currNum = this.currentNum;
// no synchronization
String result = singleStep.apply(currNum);
if (result != null) {
//Even without synchronization this block will be
//executed maximum by single thread simultaneously.
//Because each thread increments this.currentNum as part of that action,
//but no other thread will increment for the same value.
System.out.println(result);
this.currentNum++;
}
}
};
}
}
我明白我的例子完全是人为的。实现多线程“Fizz Buzz”算法启发了一本着名的书来准备“coding interview”。我只是想证明书中的示例(需要有 4 个线程)可以在不使用同步和锁的情况下解决。
最佳答案
它不是无竞争的(这就是我认为你真正要问的),因为线程在 currentNum
被另一个线程写入时读取它,没有任何同步。不保证每个线程都能看到最新的值 - 每个线程都会看到它自己上次写入的值,或者任何其他线程自此之后写入的任何值。
这可能意味着您最终在任何线程中都没有向前推进,因为每个线程可能根本看不到任何其他线程中所做的更改。您可以使用 AtomicInteger
来解决该问题。
我也不确定 this.currentNum++;
的效果是否保证可以按照它们在源线程中的顺序被其他线程看到。我怀疑理论上,输出和增量可以重新排序,例如:
this.currentNum++;
System.out.println(result);
这可能会导致输出不一致。
关于java - 我的多线程 "fizz buzz"实现线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53103065/
我是一名优秀的程序员,十分优秀!