为什么此代码不是线程安全的?
问题描述:
在下面的代码片断中,将doThings()方法声明为静态会使类是线程安全的。是这样的原因,如果多个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();
}
}
答
是的,正好。 doThings
的性质仅止于在同一实例上被多个线程同时调用。变量x
在全球基础上共享,而不是基于每个实例,因此它是不安全的。
在现实世界中的术语,把它作为与几个门的浴室 - 有人可以开一个门,然后将其锁定,但是这并不能阻止别人从通过不同的门进来......
答
我认为如果方法不是静态的,每个TestSeven对象都会使用自己的锁进行同步 - 所以每个锁都会有一个线程,并且它们都不需要等待另一个线程。如果方法声明为静态,我似乎记得它们锁定在相应的Class对象上。
答
只是要补充一点,如果你声明方法doThings是静态的,它将在类锁而不是实例锁上进行同步,这样它就会防弹。
答
是的。在这种情况下可能会出现竞争状由于您正在使方法同步而不是您的变量。所以根据竞争条件的定义,一个线程将读取变量的值,而另一个线程则可以写入变量的值。所以竞赛条件将会在那里。
答
您在this
上同步您的代码,这意味着在TestSeven的该实例上。 x
是静态的,所以它不会被锁定。这就是为什么,从不同的情况下,你可以访问相同的x
。为了解锁对该属性的锁定,您需要在该类上进行同步。
顺便说一下,你传递一个TestSeven,它是一个Thread作为Thread构造函数的参数。这是可行的,因为Thread IS-A Runnable,但不推荐,你最好使TestSeven实现Runnable –