【问题标题】:MultiThread_Unable to get the expected outputMultiThread_Unable 得到预期的输出
【发布时间】:2020-09-20 00:24:14
【问题描述】:
```
package programs;

public class TestThreads {
    
    public static void main(String[] args) {
        ThreadOne t1 = new ThreadOne();
        ThreadTwo t2 = new ThreadTwo();
        Thread one = new Thread(t1);
        Thread two = new Thread(t2);
        
        one.start();
        two.start();
    }

}

class Accum{
    
    private static Accum a = new Accum();
    private int counter = 0;
    
    private Accum() {
    }
    
    public static Accum getAccum() {
        return a;
    }
    
    public void updateCounter(int add) {
        counter +=add;
    }
    
    public int getCount() {
        return counter;
    }
}

class ThreadOne implements Runnable{
    Accum a = Accum.getAccum();

    @Override
    public void run() {
        for(int x=0;x<98;x++) {
            a.updateCounter(1000);
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
                                    
        }
        System.out.println("one "+ a.getCount());
    }
    
}

class ThreadTwo implements Runnable{
    
    Accum a = Accum.getAccum();
    @Override
    public void run() {
    for(int x=0;x<99;x++) {
        a.updateCounter(1);
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    System.out.println("two "+ a.getCount());   
    }
}
```

预期的输出应该如下

一个98098
两个98099

但我得到的一号和二号的值相同。
这是预期的还是两者都会导致不同的值?
当涉及到线程优先级时,即使 jvm 调度程序负责选择首先执行哪个线程,该程序的结果如何,其中两个 void 运行 for 循环的程序,分别为 98 和 99,这应该导致两个不同的值其他都一样

【问题讨论】:

  • 运行多次,直到得到正确的结果。或者在不同的机器、硬件或架构上运行它。当存在比赛条件时,所有赌注都将取消。当您真正想要其他结果时,您可能会得到想要的结果。

标签: java multithreading thread-safety output counter


【解决方案1】:

这是因为共享数据是 NOT 同步的。

要解决此问题,请在接触shared data 的方法上使用synchronized,以创建Accum 类Thread-Safe

示例:

class Accum{
    
    private static Accum a = new Accum();
    
    private int counter = 0;
    
    private Accum() {
        
    }
    
    public static Accum getAccum() {
        
        return a;
    }
    
    public synchronized void updateCounter(int add) {
        counter +=add;
    }
    
    public synchronized int getCount() {
        
        return counter;
    }
}

【讨论】:

    【解决方案2】:

    也许将Accum 类中的方法和字段设为静态,因为那样它会保存在一般的地方而不是实例中...

    代码:

    class Accum{
        
        private static Accum a = new Accum();
        
        private static int counter = 0;
        
        private Accum() {
            
        }
        
        public static Accum getAccum() {
            
            return a;
        }
        
        public static void updateCounter(int add) {
            counter +=add;
        }
        
        public static int getCount() {
            
            return counter;
        }
    }
    
    class ThreadTwo implements Runnable{
        
        @Override
        public void run() {
        for(int x=0;x<99;x++) {
            Accum.updateCounter(1);
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("two "+ Accum.getCount());   
        }
    }
    
    class ThreadOne implements Runnable{
        @Override
        public void run() {
            for(int x=0;x<98;x++) {
                Accum.updateCounter(1000);
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                                        
            }
            System.out.println("one "+ Accum.getCount());
        }
        
    }
    

    我对 Java 还不是很有经验,所以这可能行不通... [编辑] 我测试了它,我相信它有效

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-01
      • 2017-01-30
      • 2021-08-31
      • 1970-01-01
      • 2020-01-16
      相关资源
      最近更新 更多