我正在运行下面的类(class)。
public class RunThreads implements Runnable {
static int i;
public static void main(String[] args) {
RunThreads job = new RunThreads();
Thread alpha = new Thread(job);
Thread beta = new Thread(job);
alpha.setName("Alpha");
beta.setName("beta");
alpha.start();
beta.start();
}
public void run(){
for(;i<10;i++){
System.out.println(Thread.currentThread().getName() + i);
}
}
}
我的输出是:
beta0
beta1
Alpha0
beta2
beta4
beta5
beta6
Alpha3
Alpha8
beta7
Alpha9
我知道每次执行时都会得到不同的输出。我的问题是,为什么对于 alpha
和 beta
来说,输出的 i
值两次为 0
> 线程,即 Alpha0
和 beta0
。
i
的值已被 beta
线程增加到 1
。那么,alpha
线程如何打印出Alpha0
我可能在这里遗漏了一些非常明显的东西。谢谢!
最佳答案
当您在没有同步等的情况下访问共享数据时,事情会很可怕:
- 无法保证读取
i
的 Alpha 线程会看到beta
线程的“最新”更新,反之亦然 两个线程可以大致同时启动
i++
...并且i++
基本上是:int tmp = i; tmp++; i = tmp;
你很容易“失去”增量
如果你想使其线程安全,你应该使用 AtomicInteger
相反:
import java.util.concurrent.atomic.AtomicInteger;
public class RunThreads implements Runnable {
static AtomicInteger counter = new AtomicInteger();
public static void main(String[] args) {
RunThreads job = new RunThreads();
Thread alpha = new Thread(job);
Thread beta = new Thread(job);
alpha.setName("Alpha");
beta.setName("beta");
alpha.start();
beta.start();
}
public void run(){
int local;
while ((local = counter.getAndIncrement()) < 10) {
System.out.println(Thread.currentThread().getName() + local);
}
}
}
您的输出可能仍然出现错误的顺序(因为 alpha 线程可能“开始”写入“Alpha0”,而 beta 线程“开始”写入“beta1”,但 beta 线程得到首先锁定控制台输出),但您只会看到每个计数一次。请注意,您必须使用 getAndIncrement()
的结果进行检查和打印 - 如果您在循环体中调用 counter.get()
,您由于操作的交错,仍然可以看到重复项。
关于java - 两个线程引用一个变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42511469/