我认为我对使用关键字来防止java中线程之间的不一致有相当牢固的把握synchronized
,但是我不完全理解如果不使用该关键字会发生什么。
例如,我有一个由两个线程访问/修改的字段:
private String sharedString = "";
class OneThread extends Thread {
private Boolean mRunning = false;
public OneThread() {}
public synchronized setRunning(Boolean b) {
mRunning = b;
}
@Override
public void run() {
while (mRunning) {
// read or write to shared string
sharedString = "text from thread 1";
System.out.println("String seen from thread 1: " + sharedString);
super.run();
}
}
}
class AnotherThread extends Thread {
private Boolean mRunning = false;
public AnotherThread() {}
public synchronized setRunning(Boolean b) {
mRunning = b;
}
@Override
public void run() {
while (mRunning) {
// read or write to shared string
sharedString = "text from thread 2";
System.out.println("String seen from thread 2: " + sharedString);
super.run();
}
}
}
由于这两个线程都在sharedString
不使用同步关键字的情况下访问和修改字段,因此我预计会出现不一致。我想知道的是实际上发生了什么。在调试时,我在这种情况下仔细检查了两个线程,并注意到即使一个线程暂停,它的状态也可能是“粘滞的”。
对于上面的示例,假设两个线程都在调试器中暂停。如果我单步执行其中一个线程并让另一个暂停,我希望它会像单线程应用程序一样运行。然而,很多次在修改字段之后,访问它的下一行检索到“错误”值(与刚刚修改的值不一致的值)。
我知道这段代码不好..但我问这个问题是因为我希望有人能提供一个答案,让我们深入了解当多线程应用程序实施不佳时虚拟机中实际发生的情况。字段修改尝试不成功的线程是否有任何影响?
如果在糟糕地实现多线程代码之后,我们只是处于“未定义”行为的领域,并且学习这种行为没有任何价值,我可以接受......只是一个试图理解我的多线程菜鸟在调试器中观察。