Java 为什么这段代码不是线程安全的?
在下面的代码段中,将doThings()方法声明为static将使类线程安全。这是因为如果启动多个TestSeven线程,并且由于x是一个静态变量,可能会发生争用情况吗Java 为什么这段代码不是线程安全的?,java,scjp,Java,Scjp,在下面的代码段中,将doThings()方法声明为static将使类线程安全。这是因为如果启动多个TestSeven线程,并且由于x是一个静态变量,可能会发生争用情况吗 public class TestSeven extends Thread{ private static int x; public synchronized void doThings(){ int current = x; current++; x = c
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
的synchronized
特性只会阻止同一实例上的多个线程同时调用它。变量x
是在全局基础上共享的,而不是在每个实例的基础上共享的,因此它是不安全的
在现实世界中,把它想象成一个有多扇门的浴室——有人可以打开一扇门然后锁上,但这并不能阻止其他人从另一扇门进来……我认为如果这个方法不是静态的,每个TestSeven对象都会使用自己的锁进行同步——所以每个锁都有一个线程,他们都不必等待另一个线程。如果该方法被声明为静态,我似乎记得它们锁定在相应的类对象上。只是要补充一点,如果您声明方法是静态的,它将在类锁而不是实例锁上同步,因此它将是防弹的。是的。在这种情况下可能会出现竞争条件。在使方法同步时,请不要使用变量。因此,根据竞争条件的定义,一个线程将读取变量的值,而同步方法中的另一个线程可以写入该值。因此会有一个竞争条件。您在
上同步代码,这意味着在TestSeven的实例上x
是静态的,因此它不会被锁定。这就是为什么您可以从不同的实例访问相同的x
。为了在该属性上解除锁定,需要在类上进行同步 +1:锁定当前线程(这里就是这种情况)几乎总是毫无意义的。顺便说一句,您将TestSeven作为线程参数传递给线程构造函数。这是因为线程是可运行的,但不推荐这样做,您最好让TestSeven实现为可运行的