2014-12-06 48 views
1

我正在通过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[]) 
    { 
    } 
} 

我的答案是肯定的,因为只有两个方法,都同步,因此,尽管他们中的一个运行时,它持有对象的锁,其他不能运行。

但是,官方回答是NO,并且解释是变量int x是公共的,可以由线程修改,而另一个线程在同步方法之一内。那可能吗?? synchronized方法是否保留了这个线程,意味着该对象中的所有内容都包含公共变量?

+0

是的,这是可能的。 'synchronized'方法只能防止在同一个对象上同时执行** other **'synchronized'方法。 – 2014-12-06 19:23:32

回答

7

关键字​​的所有功能都会自动防止在对象的单个实例上多次调用​​方法。这意味着无论何时调用同步方法,都必须先退出,才能在同一个实例上执行任何其他的同步方法。

但是,直接字段访问是从来没有受到任何形式的Java锁定,所以公共领域使这个类非常不安全。

+0

那么,你是不是说一个非同步方法可以在另一个线程持有该对象上的锁的同时访问公共变量,并且正在其中一个同步方法中工作?如果是这样,那么'持有对象的锁'的含义是什么? – user3516726 2014-12-06 19:36:10

+0

@ user3516726是的。不同对象上的任何方法*或*对象本身的任何非同步方法都可以随意访问该字段。 – 2014-12-06 19:37:36

+0

我认为当一个同步方法在一个对象上持有一个锁时,没有其他线程可以对该对象执行任何操作,包括更改其公共变量。这不正确吗? – user3516726 2014-12-06 19:40:50

0

使setter和getter同步的唯一目的是在访问它时防止竞争条件。但是由于x是最终的,任何代码都可以直接访问它,而无需使用setter或者在不使用getter的情况下访问它。使x公开会否定同步方法提供的所有安全性。

1

你是正确的锁保持在对象上,但它意味着只有一个线程可以在任何syncronised方法。但是该字段是公开的,所以其他线程不需要在sycronized块内部。

让我们说在时间T1,一个线程在setX()内部通过调用 queenInstance.setX(10);

Howwver,在同一个实例中,其他线程正试图为此变量设置值: - queenInstance.x = 12;

这是不可预测的,会输出什么。