繁体   English   中英

有和没有静态变量的Java同步

[英]Java Synchronisation with and without static variable

我一直在研究Java中的同步,并尝试运行以下程序

    public class Example {
        public static void main(String[] args) {
            Counter counterA = new Counter();
            Counter counterB = new Counter();
              Thread  threadA = new CounterThread(counterA);
              Thread  threadB = new CounterThread(counterB);

              threadA.start();
              threadB.start(); 
        }
    }

    class CounterThread extends Thread {
        protected Counter counter = null;

        public CounterThread(Counter counter){
           this.counter = counter;
        }
        public void run() {
        for(int i=0; i<2; i++){
              counter.add(i);
           }
        }
    }

    class Counter {
         long count = 0;
         public synchronized void add(long value){
          this.count += value;
          System.out.println(this.count);
        }
    }

当我运行上面的代码时,当我将Example类作为Java应用程序运行或调试Example类时,它会提供相同的输出

 0
 1
 0
 1

但是如果我将计数器类的count变量的访问修饰符修改为static,如下所述:

    static long count = 0;

现在,如果尝试运行Example类,则输出为

 0
 1
 0
 2

但是当我调试Example类时,我得到的输出为

 0
 1
 1
 2

谁能帮助我了解区别。 在此先感谢您道歉,因为我是多线程概念的新手

每个实例都有自己的实例变量副本,但它们共享静态变量。 由于您有类的两个实例,并且在这些实例上有两个线程运行:

        Counter counterA = new Counter();
        Counter counterB = new Counter();
        Thread  threadA = new CounterThread(counterA);
        Thread  threadB = new CounterThread(counterB);

因此效果很明显。 count为非静态时,两个线程不会影响两个不同对象的count 但是,当count为静态时,两个线程将在两个实例共享的同一变量上工作。

当您有两个独立的线程在运行时,执行顺序是动态的,具体取决于线程调度程序选择执行线程的方式。 使用调试器不一定会对其产生影响,实际上,您可能会在正常执行程序时看到不同的结果。

synchronized仅保护您免受两个调用者同时同一实例上输入方法的困扰。 因此,它基本上根本不会影响您的示例。

非静态情况:每个线程都在更新其自己的Counter.count实例。 您可以得到0-1-0-1或0-0-1-1(可能性很小)作为输出。

静态情况:每个线程通过两个不同的 Counter实例更新相同的Counter.count 您可以获得0-0-1-2、0-1-1-2和0-1-0-2。

为什么最后选择? 您只影响静态的Coutner.count实例,而不影响静态的Counter实例。 因此,两个线程都可以位于Counter.add内部,并且一个线程可能已经加载了0进行输出,但其他线程随后对其进行了更新并输出1,只有第一个线程才输出0。

其中的0-0-1-2,0-1-1-2或0-1-0-2你得到的是不是在所有定义的, 并不依赖于调试和发布模式。 但是,由于编译器产生的汇编代码不同,在调试和释放模式下接收不同的结果是很常见的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM