我正在阅读一本Java书,并发现了以下问题。
在下面的代码中,类线程是否安全?
public class Queen
{
public int x;
public synchronized int getX()
{
return x;
}
public synchronized void setX(int x)
{
this.x = x;
}
public static void main(String args[])
{
}
}
我的回答是肯定的,因为只有两个方法都是同步的,所以当其中一个方法正在运行时,它会锁定对象,而另一个方法无法运行。
然而,官方答案是否定的,并且解释是变量int x是公共的并且可以由线程修改而另一个线程在其中一个同步方法中。那可能吗??同步方法是否在此处保留线程,这意味着该对象中的所有内容都包括公共变量?
答案 0 :(得分:7)
synchronized
关键字所做的全部操作会自动阻止在对象的单个实例上多次调用synchronized
方法。这意味着无论何时调用synchronized方法,都必须在任何其他同步方法可以在同一实例上执行之前退出。
但是,直接字段访问从不受到Java中任何形式的锁定的影响,因此公共字段使此类非常不安全。
答案 1 :(得分:1)
你是对的锁是对象,但这意味着只有一个线程可以在任何同步方法中。但是该字段是公共的,因此其他线程不需要在sycronized块内部。
让我们在时间T1,通过调用setX()内部的一个线程 queenInstance.setX(10);
Howwver,在同一个实例中,其他线程试图为此变量设置值: - queenInstance.x = 12;
无法预测输出的内容。
答案 2 :(得分:0)
使setter和getter同步的唯一目的是在访问它时防止竞争条件。但由于x是公共的,任何代码都可以直接访问它,而无需使用setter或不使用getter访问它。使x public将否定Synchronized方法提供的所有安全性。