简体   繁体   English

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

[英]Java Synchronisation with and without static variable

I have been studying about synchronization in java and tried to run the following program 我一直在研究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);
        }
    }

when i run the above code , it gives me the same output when i run Example class as java application or when i debug the Example class 当我运行上面的代码时,当我将Example类作为Java应用程序运行或调试Example类时,它会提供相同的输出

 0
 1
 0
 1

But if i modify the access modifier of count variable of counter class as static like mentioned below : 但是如果我将计数器类的count变量的访问修饰符修改为static,如下所述:

    static long count = 0;

and now if try to run the Example class i get the output as 现在,如果尝试运行Example类,则输出为

 0
 1
 0
 2

but when i debug the Example class i get the output as 但是当我调试Example类时,我得到的输出为

 0
 1
 1
 2

Can anyone help me to understand the difference. 谁能帮助我了解区别。 Thanks in advance and apologies because i am new to multithreading concepts 在此先感谢您道歉,因为我是多线程概念的新手

Each instance has its own copy of instance variable(s) but they share the static variable. 每个实例都有自己的实例变量副本,但它们共享静态变量。 As you have two instances of your class and two threads operating on these instances: 由于您有类的两个实例,并且在这些实例上有两个线程运行:

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

So the effect is clear. 因此效果很明显。 When the count is non-static, two threads do not affect the count of two different objects. count为非静态时,两个线程不会影响两个不同对象的count But when count is static, two threads work on the same variable shared by two instances. 但是,当count为静态时,两个线程将在两个实例共享的同一变量上工作。

When you have two independent threads in action, the execution order is dynamic depending on how Thread Scheduler picks a thread to execute. 当您有两个独立的线程在运行时,执行顺序是动态的,具体取决于线程调度程序选择执行线程的方式。 Using a debugger not necessarily does affect it , infact you may see different result with normal execution of your program. 使用调试器不一定会对其产生影响,实际上,您可能会在正常执行程序时看到不同的结果。

synchronized only protects you from two callers entering a method on the same instance at the same time. synchronized仅保护您免受两个调用者同时同一实例上输入方法的困扰。 So it basically does not affect your example at all. 因此,它基本上根本不会影响您的示例。

Non-static case: Each thread is updating its own Counter.count instance. 非静态情况:每个线程都在更新其自己的Counter.count实例。 You can get either 0-1-0-1 or 0-0-1-1 (much less likely) as output. 您可以得到0-1-0-1或0-0-1-1(可能性很小)作为输出。

Static case: Each thread is updating the same Counter.count via two different Counter instances. 静态情况:每个线程通过两个不同的 Counter实例更新相同的Counter.count You can get either 0-0-1-2, 0-1-1-2 AND 0-1-0-2. 您可以获得0-0-1-2、0-1-1-2和0-1-0-2。

Why the last option? 为什么最后选择? You only affect a static Coutner.count instance, not a static Counter instance. 您只影响静态的Coutner.count实例,而不影响静态的Counter实例。 So both threads can be inside Counter.add and one thread may have already loaded 0 for outputting it, but the other threads then updates it and outputs 1 and only then the first thread outputs its 0. 因此,两个线程都可以位于Counter.add内部,并且一个线程可能已经加载了0进行输出,但其他线程随后对其进行了更新并输出1,只有第一个线程才输出0。

Which of 0-0-1-2, 0-1-1-2 or 0-1-0-2 you get is not defined at all and does NOT depend on debug & release modes. 其中的0-0-1-2,0-1-1-2或0-1-0-2你得到的是不是在所有定义的, 并不依赖于调试和发布模式。 It is quite common, however, to receive different results in debug & release modes due to differences in the assembly code produced by the compiler. 但是,由于编译器产生的汇编代码不同,在调试和释放模式下接收不同的结果是很常见的。

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

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