0

我有一个创建 2 个线程的 Java 程序,在这 2 个线程内,它们试图将全局变量更新abc为不同的值,比如说整数 1 和整数 3。

假设他们同时(在同一毫秒)执行代码,例如:

public class MyThread implements Runnable{
    public void run(){
        while(true){
            if (currentTime == specificTime){
                abc = 1; //another thread update abc to 3
            }
        }
    }
} 

在这种情况下,我们如何确定变量的结果abc?我很好奇操作系统如何安排执行?

(我知道应该使用 Synchronize,但我只是想自然地知道系统将如何处理这种冲突问题。)

4

6 回答 6

3

操作系统对此几乎没有参与:在您的线程运行时,分配给的内存abc由运行您的程序的 JVM 控制,因此您的程序处于控制之中。

当两个线程访问相同的内存位置时,最后一个写入者获胜。然而,哪个特定线程成为最后一个写入者是不确定的,除非您使用同步。

此外,如果您不特别注意访问共享数据,一个线程甚至可能看不到另一个线程写入该abc位置的结果。

为避免同步问题,您应该使用同步或其中一个java.util.concurrent.atomic类。

于 2013-09-21T12:50:59.960 回答
3

abc从 Java 的角度来看,如果不是易失性的或通过适当的同步访问,情况就相当简单。

让我们假设abc最初是0。在您的两个线程分别将其更新为 1 和 3 后,abc可以在三种状态下观察到:0、1 或 3。您获得的值不是确定性的,结果可能因一次运行而异。

于 2013-09-21T12:56:02.413 回答
2

取决于操作系统、运行环境等。

有些环境实际上会阻止你这样做——称为线程安全。

否则结果是完全不可预测的,这就是为什么这样做如此危险。

它主要取决于哪个线程最后更新了它的值。一个线程将在另一个线程之前获得 CPU 周期以首先执行原子操作。

另外,我认为操作系统不会调度线程,因为在大多数操作系统中,是程序负责它们,并且没有像同步这样的显式调用或线程池模型,那么我认为顺序执行很难预测。它是一个非常依赖环境的东西。

于 2013-09-21T12:45:10.010 回答
1

从系统的角度来看,结果将取决于许多无法提前知道的软件、硬件和运行时间因素。从这个角度来看,没有冲突也没有问题。

从程序员的角度来看,结果不是确定性的,因此是一个问题/冲突。冲突需要在设计时解决。

于 2013-09-21T12:47:56.717 回答
1

在这种情况下,我们如何确定变量的结果abc?我很好奇操作系统如何安排执行?

结果将不是确定性的,因为该值将是最后写入的值。您不能对结果做出任何保证。执行与任何其他执行一样安排。由于您要求在代码中不同步,JVM 不会为您强制执行任何操作。

我知道应该使用 Synchronize,但我只是想自然地知道系统将如何处理这种冲突问题。

简单的说:不会的,至于系统没有冲突。只有你,程序员,才会出现问题,因为你最终会遇到数据竞争而不是确定性行为。这完全取决于你。

于 2013-09-21T12:55:15.040 回答
1

只需将 volatile 修饰符添加到您的变量中,然后它将通过所有线程进行更新。线程读取它会得到它的实际价值。volatile意味着对于访问它的所有线程,该值将始终是最新的。

于 2013-09-21T13:16:57.157 回答