gpt4 book ai didi

java - 我的多线程 "fizz buzz"实现线程安全吗?

转载 作者:行者123 更新时间:2023-11-29 04:14:43 27 4
gpt4 key购买 nike

出于教育目的,我正在使用多线程实现经典的“嘶嘶声”问题。

“嘶嘶声”游戏是:

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 个线程:

  • 如果第一个线程不是 3 或 5 的倍数,则打印数字并递增当前计数器。
  • 第二个线程打印“fizz”...
  • 第三个线程打印“嗡嗡声”……
  • 第四个线程打印“fizz buzz”...

我不使用任何锁定和线程同步机制。我的多线程“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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com