在下面的代码片段中,将doThings()方法声明为static将使该类成为线程安全的。原因是如果启动了多个TestSeven线程,并且因为x是静态变量,可能会出现竞争条件?
public class TestSeven extends Thread{
private static int x;
public synchronized void doThings(){
int current = x;
current++;
x = current;
}
public void run(){
doThings();
}
public static void main(String args[]){
TestSeven t = new TestSeven();
Thread thread = new Thread(t);
thread.start();
}
}
答案 0 :(得分:16)
是的,确切地说。 synchronized
的{{1}}性质仅阻止多个线程同时在同一个实例上调用它。变量doThings
在全局的基础上共享,而不是基于每个实例,因此它不安全。
在现实世界中,把它想象成一个有几个门的浴室 - 有人可以打开一扇门然后将其锁上,但这并不能阻止其他人通过不同的门进来...
答案 1 :(得分:1)
我认为如果该方法不是静态的,则每个TestSeven对象将使用自己的锁进行同步 - 因此每个锁将有一个线程,并且它们都不必等待另一个线程。如果该方法被声明为static,我似乎记得它们锁定了相应的Class对象。
答案 2 :(得分:1)
只是要补充一点,如果你声明方法doThings是静态的,它将在类锁上而不是实例锁同步,这样就可以防弹了。
答案 3 :(得分:1)
是肯定的。这种情况可能会发生。正如您使方法同步而不是您的变量。因此根据竞争条件的定义,一个线程将读取变量的值,而其他同步方法可以写入它。因此会出现竞争条件。
答案 4 :(得分:1)
您在this
上同步代码,意味着TestSeven的实例。 x
是静态的,因此不会被锁定。这就是为什么从不同的实例中,您可以访问相同的x
。为了解除对该属性的锁定,您需要在类上进行同步。