gpt4 book ai didi

Java同步计数器相同的值由不同的线程打印

转载 作者:行者123 更新时间:2023-11-30 06:40:42 24 4
gpt4 key购买 nike

我正在用 Java 使用同步方法编写一个同步计数器。代码如下

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class Counter implements Runnable {
private static int counter = 0;
private static final int limit = 1000;
private static final int threadPoolSize = 5;

public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
for (int i = 0; i < threadPoolSize; i++) {
executorService.submit(new Counter());
}
executorService.shutdown();
}

@Override
public void run() {
incrementCounter();
}

private synchronized void incrementCounter() {
while (counter < limit) {
System.out.println(Thread.currentThread().getName() + " : " + counter);
counter++;
}
}
}

代码运行良好。但在某些时候,两个线程正在打印相同的数字,

pool-1-thread-2 : 29
pool-1-thread-2 : 30
pool-1-thread-1 : 30
pool-1-thread-1 : 32

在上面的输出中,线程 2 和 1 都在打印 30。我不知道为什么会这样。感谢任何帮助

最佳答案

当您使用synchronized 方法时,执行该方法的线程将锁定Counter 类的当前实例,以便其他线程可以同时递增counter 没有任何限制的值。

这是因为您在循环内创建了 Counter 类的五个不同实例:

 for (int i = 0; i < threadPoolSize; i++) {
executorService.submit(new Counter());
}

所以可能有五个线程可以同时执行 incrementCounter() 方法,因为它们锁定了 Counter 类的五个不同实例(当您使用 synchonized 方法,您实际上是在锁定 this当前类实例)。

您可以创建一个新的 static lock 对象,必须对其进行同步,以便池中的所有线程都拥有并共享相同的 common 锁对象:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

class Counter implements Runnable {
private static AtomicInteger counter = new AtomicInteger(0);
private static final Object lock = new Object();
private static final int limit = 1000;
private static final int threadPoolSize = 5;

public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
for (int i = 0; i < threadPoolSize; i++) {
executorService.submit(new Counter());
}
executorService.shutdown();
}

@Override
public void run() {
incrementCounter();
}

private void incrementCounter() {
synchronized (lock) {
while (counter.get() < limit) {
System.out.println(Thread.currentThread().getName() + " : " + counter.get());
counter.incrementAndGet();
}
}
}
}

此外,由于在这种情况下您正在执行read-update-write 操作,因此您应该考虑使用 AtomicInteger 代替 int 使操作成为原子的原语,即操作将在单个事务中发生,并且其他线程始终可以看到最新值。

关于Java同步计数器相同的值由不同的线程打印,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57347443/

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