2014-12-06 84 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;

這是不可預測的,會輸出什麼。