【发布时间】:2019-04-28 19:15:47
【问题描述】:
我正在学习线程安全。我写了一个例子,得到了一个问题。
首先,我的main()函数是一样的:
public class ThreadSafe {
public static void main(String[] args) {
System.out.println("Thread Safe");
SafeSharedRunnable r = new SafeSharedRunnable();
// Access the same resource
Thread tA = new Thread(r);
Thread tB = new Thread(r);
Thread tC = new Thread(r);
Thread tD = new Thread(r);
tA.start();
tB.start();
tC.start();
tD.start();
}
}
然后我有两个 Runnable 版本,其中 synchronized() 放置在不同的位置,因此,一个版本有效,一个无效。
工作版本:
public class SafeSharedRunnable implements Runnable {
int count = 5;
@Override
public void run() {
// Thread Safe, must be outside of while(), why?
synchronized ("") {
while (count > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
System.out.println("Current value is: " + count--);
}
}
}
}
正确结果:
run:
Thread Safe
Current value is: 5
Current value is: 4
Current value is: 3
Current value is: 2
Current value is: 1
BUILD SUCCESSFUL (total time: 0 seconds)
非工作版本:
public class SafeSharedRunnable implements Runnable {
int count = 5;
@Override
public void run() {
while (count > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
// Thread Safe
synchronized ("") {
System.out.println("Current value is: " + count--);
}
}
}
}
错误的结果:
run:
Thread Safe
Current value is: 5
Current value is: 4
Current value is: 2
Current value is: 3
Current value is: 1
Current value is: 0
Current value is: -1
Current value is: -2
BUILD SUCCESSFUL (total time: 0 seconds)
如您所见,不同 synchronized() 块的不同位置会导致不同的结果。在我的理解中,关键资源冲突应该发生在这行代码上:
System.out.println("Current value is: " + count--);
但为什么我必须将 synchronized() 放在 while() 块之外?这是否意味着我应该同步所有包含变量“count”的代码?感谢您的详细解释。
我不认为这是与竞争条件问题的重复,因为我没有询问有关多线程的任何一般知识。相反,这是一个关于多线程如何进入代码流的详细问题。
【问题讨论】:
-
synchronized ("")- 这确实有效,因为 Java 部署了String实习生String常量。但是你真的应该使用专用的lock-object,可能是this。synchronized的位置确实很重要,因为它定义了哪些语句是专门执行的。 -
同步 (""):永远不要那样做。您真的不希望几个不相关的任务相互干扰,因为它们在全局空字符串上同步。
-
为什么代码行的位置很重要?
-
I should synchronize all the codes that contains variable "count"?如果你希望这些操作是线程安全的,是的。
标签: java multithreading