gpt4 book ai didi

java - 使用同步方法测试两个线程递增单个int的结果令人困惑

转载 作者:行者123 更新时间:2023-12-03 13:18:12 25 4
gpt4 key购买 nike

我试图弄清楚对单个数据进行更改的多个线程如何工作。我最近了解了synchronized关键字的功能,但是经过某种测试仍然使我感到困惑。
这是完整的代码:

public class TestSyncTest{
public static void main(String[] args){
TestSync job = new TestSync();

Thread a = new Thread(job);
Thread b = new Thread(job);

a.start();
b.start();
}
}

class TestSync implements Runnable{
private int balance;

public void run(){
for(int i = 0; i < 50; i++){
increment();
System.out.println("balance is " + balance);
}
}

public synchronized void increment(){
int i = balance;

try{
Thread.sleep(10);
} catch(InterruptedException ex){
ex.printStackTrace();
}

balance = i + 1;
}
}
基本上,这是演示如何使JVM通过一个线程在单个数据上完成一系列操作,而不会导致其他线程参与并破坏事情。 increment()synchronized,它使该方法成为一个块,一次可以处理一个线程。 sleep()只是为了模拟很多代码,这些代码需要花费时间,否则其他线程可能会跳入该代码。运行此代码时,那里的 sleep()无关紧要,因为整个方法都是 synchronized。因此,输出看起来不错,干净且正确,如下所示:
>java TestSyncTest
balance is 1
balance is 2
balance is 3
balance is 4
balance is 5
balance is 6
. . .
balance is 98
balance is 99
balance is 100
balance完全按预期计数。删除 synchronized后,将显示以下输出:
>java TestSyncTest
balance is 1
balance is 1
balance is 2
balance is 2
balance is 3
balance is 4
balance is 4
balance is 5
balance is 5
balance is 6
balance is 6
. . .
balance is 48
balance is 48
balance is 49
balance is 49
balance is 50
balance is 50
balance is 51
这也是预期的,因为另一个线程不断跳入当前线程的敏感增量过程的中间,从而导致一致的错误。我遇到的问题是 increment()方法看起来像这样:
public synchronized void increment(){
int i = balance;
balance = i + 1;
}
在这里,方法是 synchronized,但是里面的第二条语句或多或少地紧随第一条语句,这是整个输出的一个示例:
>java TestSyncTest
balance is 2
balance is 3
balance is 1
balance is 5
balance is 6
balance is 7
balance is 8
balance is 9
balance is 10
balance is 11
balance is 12
balance is 13
balance is 14
balance is 15
balance is 16
balance is 17
balance is 18
balance is 19
balance is 20
balance is 21
balance is 22
balance is 23
balance is 24
balance is 25
balance is 26
balance is 27
balance is 28
balance is 29
balance is 30
balance is 31
balance is 32
balance is 33
balance is 34
balance is 35
balance is 36
balance is 37
balance is 38
balance is 39
balance is 40
balance is 41
balance is 42
balance is 43
balance is 44
balance is 45
balance is 46
balance is 47
balance is 48
balance is 49
balance is 50
balance is 51
balance is 52
balance is 53
balance is 4
balance is 54
balance is 55
balance is 56
balance is 57
balance is 58
balance is 59
balance is 60
balance is 61
balance is 62
balance is 63
balance is 64
balance is 65
balance is 66
balance is 67
balance is 68
balance is 69
balance is 70
balance is 71
balance is 72
balance is 73
balance is 74
balance is 75
balance is 76
balance is 77
balance is 78
balance is 79
balance is 80
balance is 81
balance is 82
balance is 83
balance is 84
balance is 85
balance is 86
balance is 87
balance is 88
balance is 89
balance is 90
balance is 91
balance is 92
balance is 93
balance is 94
balance is 95
balance is 96
balance is 97
balance is 98
balance is 99
balance is 100
它以2开头,后面出现1代替4,后面出现4则出现在53和54之间。总是有一些数字混淆,但最终结果始终是100,而它本身并不是总是输出中的最后一个。
请帮助我了解这里发生了什么。

最佳答案

即使increment()方法是synchronized,您仍然具有以下竞争条件:

public void run(){
for(int i = 0; i < 50; i++){
increment();
System.out.println("balance is " + balance); // <-- here
}
}
在读取 System.out.println中的变量balance期间。一个线程可能正在另一个线程正在读取该变量的同时,在 increment()方法中修改该变量。
尽管如此,由于 System.out.println方法在内部 synchronizes,所以该竞争条件不会反射(reflect)在您的输出中。
在第一个代码段中,由于 sleep调用,线程按顺序输出结果。当您删除该调用时,不能保证 System.out.println产生的输出将被排序。

关于java - 使用同步方法测试两个线程递增单个int的结果令人困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66790080/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com