【问题标题】:Minumum and Maximum value of class member类成员的最小值和最大值
【发布时间】:2018-08-10 15:16:21
【问题描述】:

我试图了解classMember 的可能值是什么,即两个线程是更新,当我运行程序时,输出始终为 20,但我想了解它发生的原因以及最低限度是多少,最大值为classMember

public class TestClass {


public int classMember = 0;
    private void updateCM() {
        for (int i = 0; i < 10; i++) {
            classMember++;
        }
    }
public static void main(String[] args) {

    TestClass mainClass = new TestClass();
    Thread t1 = new Thread(mainClass::updateCM);
    Thread t2 = new Thread(mainClass::updateCM);

    t1.start();
    t2.start();

    while(t1.isAlive() || t2.isAlive()) {}

    System.out.println(mainClass.classMember);
}

}

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    我认为你需要阅读这个 Stackoverflow 线程

    Make multiple threads use and change the same variable

    由于您在同一个实例中更新同一个变量,您可能会遇到同步问题。这种情况下合适的关键字是volatile。但是,即使您将 volatile 设置为您的变量,这也是不够的,因为 ++ 实际上不是单个操作,而是三个操作,这使得它不是原子的。

    我也会引用这段话

    虽然这会处理内存同步,但它不一定能保护您免受竞争条件的影响。同样重要的是要意识到 ++ 实际上是 3 个操作:获取当前值,递增它,然后再次存储它。如果多个线程尝试执行此操作,则存在可能导致 ++ 操作丢失的线程竞争条件。 在这种情况下,您应该使用包装了 volatile int 字段的 AtomicInteger 类。它为您提供诸如 incrementAndGet() 之类的方法,这些方法以线程安全的方式完成该字段的递增工作。

    【讨论】:

    • ++ 非原子操作实际上是非常重要的一点。如果交互时间较长,您可能会看到不一致的结果。
    • volatile sill 并没有解决自增操作的非原子性。 stackoverflow.com/questions/7805192/…
    • @MarkJeronimus 谢谢。我看到它在文本中没有很好地说明 voliatize 与 ++ 操作的关系。我编辑了它。
    【解决方案2】:

    最小值为初始化值,即0。

    关于最大值,虽然您创建了两个 Thread 实例,但两个实例都使用相同的 TestClass 实例,因此,将 classMember 变量递增 2 倍 * 10 倍,您将得到 20 的值。

    【讨论】:

    • 2*10 实际上并不能保证,因为存在从两个线程同时递增 classMember 的竞争条件。
    • 我从来没有说过这是有保证的
    【解决方案3】:

    增量不是原子操作,因此每次运行程序时结果都可能不同。在这种情况下,我认为,在处理器给第二个线程一个时间来执行它的操作之前,第一个线程刚刚完成递增变量的值。但是,例如,如果您启动两个线程,其中第一个线程将变量的值递减十亿次,而第二个线程则相反——将其递增十亿次,您会得到一些非常意想不到的结果(当然,如果您是不会使这个变量成为线程安全的)。

    【讨论】:

      【解决方案4】:
      TestClass mainClass = new TestClass(); 
      

      现在该值设置为 0。

      t1.start(); // 0-10
      t2.start(); /10- 20
      

      最后,classMember 是 20。

      【讨论】:

        【解决方案5】:

        很可能是由于“运气”或“样本太少”(如果您愿意的话)。 JIT 编译器还没有完成它的工作,所以无论运行什么都可能不是最佳的并且使用简单的技术。

        如果您将最大值从 10 更改为 1,000,000,您看到总数确实不会相加,并且在不同的运行中会产生不同的结果。

        【讨论】:

          【解决方案6】:

          10 到 20(含)之间的所有值都是可能的结果。

          在最坏的情况下,一个线程的每个增量(不是原子的,由读内存、增量、写内存组成)都会与其他线程交错。

          可能的交错(为了简洁省略了“增加”操作):

          Thread1  Thread2
          Read 0
                   Read 0
          Write 1
                   Write 1
          Read 1
                   Read 1
          Write 2
                   Write 2
          Read 2
                   Read 2
          Write 3
                   Write 3
          Read 3
                   Read 3
          Write 4
                   Write 4
          Read 4
                   Read 4
          Write 5
          Read 5
                   Write 5
                   Read 5
          Write 6
          Read 6
                   Write 6
                   Read 6
          Write 7
          Read 7
                   Write 7
                   Read 7
          Write 8
          Read 8
                   Write 8
                   Read 8
          Write 9
          Read 9
                   Write 9
                   Read 9
                   Write 10
          Write 10
          

          另一种可能的交错:

          Thread1  Thread2
          Read 0
                   Read 0
                   Write 1
                   Read 1
                   Write 2
                   Read 2
                   Write 3
                   Read 3
                   Write 4
                   Read 4
                   Write 5
                   Read 5
                   Write 6
                   Read 6
                   Write 7
                   Read 7
                   Write 8
                   Read 8
                   Write 9
                   Read 9
                   Write 10
          Write 1
          Read 1
          Write 2
          Read 2
          Write 3
          Read 3
          Write 4
          Read 4
          Write 5
          Read 5
          Write 6
          Read 6
          Write 7
          Read 7
          Write 8
          Read 8
          Write 9
          Read 9
          Write 10
          

          【讨论】:

          • 问题是关于变量的最小值和最大值。与可能的结果无关。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-04-02
          • 2019-01-02
          • 2017-10-02
          • 2016-04-10
          • 2019-01-09
          • 1970-01-01
          相关资源
          最近更新 更多