为什么这些同步方法不断为我提供不同的输出?

问题描述

我需要可以访问同一数据的线程同时执行,而又不会互相干扰,所以我一直在尝试使用同步方法,而不是使用Thread.join()。问题是我什么都看不到,它给了我与使用它们之前相同的结果。我什至不知道我到底在做什么错,同步 方法假设可以阻止其他同步方法在完成之前执行,对吗?希望你能给我一些线索。

public class ThreadSync{
    public static void main(String[] args) throws InterruptedException {
         //if execute properly  
         //output can't be other than 0
         while(true) {
         ChangeValue counter = new ChangeValue();
         Threads t  = new Threads(counter,"up");
         Threads t2 = new Threads(counter,"down");
         Threads t3 = new Threads(counter,"print");
         t.start();
         t2.start();
         t3.start();
         }
    }
}
class Threads extends Thread{
    Threads(ChangeValue obj,String act){
        counter = obj;
        action = act;
    }
    @Override
    public void run() {
        switch(action) {
        case ("up"):    counter.up();    break;
        case ("down"):  counter.down();  break;
        case ("print"): counter.print(); break;     
        }
    }
    ChangeValue counter;
    String action;
}
class ChangeValue{  
    public synchronized void up()    { value++; }
    public synchronized void down()  { value--; }
    public synchronized void print() { System.out.println(value); }
    public int value = 0;
}

解决方法

同步仅确保方法不会同时执行。但是,它不能保证任何执行顺序。

您需要确保在其他线程终止之前不执行print()。这可以通过连接线程来实现。为此,执行

t.join();
t2.join();

在启动打印线程之前或在执行其逻辑之前。

请注意,同步仍然是明智的,因为它确保自动执行增量和减量操作。也就是说,在执行count时读取,递增和写入count++会立即执行 (另请参见:Why is i++ not atomic?)。因此,它阻止了以下执行顺序:

  • [线程“向上”]:将值count加载到0
  • [线程“关闭”]:将值count加载到0
  • [线程“向上”]:将count增至1
  • [线程“向下”]:将count减为-1
  • [线程“向上”]:将count存储到值1
  • [线程“关闭”]:将count存储到值-1

(这是数据库术语中的“丢失的更新”。)

,

synchronized使您的线程无法同时访问该字段,但当然不能保证线程执行的顺序。 例如,如果偶然地首先执行“ Up”线程,然后执行“ Print”线程,最后执行“ Down”线程,则即使所有线程完成后计数器值为0,输出也将为1。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...