![](/img/trans.png)
[英]sharing and updating a variable among multiple threads without synchronisation in 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.