簡體   English   中英

將getter與輸入處理方法分開的類可以被認為是“線程安全的”嗎?

[英]Can a class with getters separate from input processing methods be considered “thread-safe”?

我正在讀一本關於Java的書,有一個練習題,他們用一個私有變量聲明了一個類,一個公共void方法做了一些昂貴的操作來計算然后設置私有變量,另一個公共方法返回私人變量。 問題是“如何使這個線程安全”,一個可能的答案是“同步兩個方法中的每一個”,另一個可能的答案是“這個類不能成為線程安全的”。

我認為類不能成為線程安全的,因為即使你同步這兩個方法,你可能會遇到Thread1會調用setter的情況,在Thread1可以調用getter之前,Thread2可能會執行並調用setter,這樣當Thread1去檢索結果會得到錯誤的信息。 這是看待事物的正確方法嗎? 書中提出的正確答案是,通過同步這兩種方法可以使類成為線程安全,現在我很困惑......

我認為類不能成為線程安全的,因為即使你同步這兩個方法,你可能會遇到Thread1會調用setter的情況,在Thread1可以調用getter之前,Thread2可能會執行並調用setter,這樣當Thread1去檢索結果會得到錯誤的信息。 這是看待事物的正確方法嗎?

你是對的。 無法保證線程不會在類中調用每個方法之間調用任何一種方法。

如果你想這樣做,那將需要一個包裝類。 所以如果帶有getter和setter的類是這樣的:

class Foo
{
    private static int bar;

    public static synchronized void SetBar(int z) { ... }
    public static synchronized int GetBar() { ... }
}

包裝類看起來像這樣:

class FooWrapper
{

    public synchronized int SetGetBar(int z)
    {
        Foo.SetBar(z);
        return Foo.GetBar();
    }

}

保證這一點的唯一方法是,如果你可以保證所有的調用都將通過你的包裝類,而不是直接到類Foo。

當你使這兩個同步時,getter和setter本身是線程安全的。 進一步來說:

  • 當您調用setter時,可以保證變量的值是方法完成時設置的值。
  • 當您調用getter時,可以保證返回值是您進行調用時變量的值。

    但是,使getter和setter 本身是線程安全的並不意味着應用程序作為一個整體 (即使用此類的任何東西)是線程安全的。 如果您的線程想要調用setter,那么在調用getter時獲取相同的值,這涉及在不同級別上的同步。

    就線程安全性而言,線程安全類不需要控制如何調用其方法(例如,它不需要控制線程交換其調用的方式),但它需要確保它們何時 ,方法做他們應該做的事。

  • Java中的synchronized是一個對象范圍的鎖。 任何給定對象的一個synchronized方法一次只能在任何給定的線程上執行。 讓我們來上課:

    class Foo
    {
        private int bar;
    
        public synchronized void SetBar() { ... }
        public synchronized int GetBar() { ... }
    }
    
    • 線程1調用SetBar() 線程1獲取對象鎖。
    • 線程2想要調用SetBar() ,但線程1持有鎖。 線程2現在排隊等待線程1將釋放它時獲取鎖定。
    • 線程1完成執行SetBar()並釋放鎖。
    • 線程2立即獲取鎖並開始執行SetBar()
    • 線程1調用GetBar() 線程1現在排隊等待線程2將釋放它時獲取鎖定。
    • 線程2完成執行SetBar()並釋放鎖。
    • 線程1獲取鎖,執行GetBar() ,並完成它。

    你做了兩次工作,但沒有造成任何競爭條件。 兩次工作可能會或可能不會是錯誤的,具體取決於它是什么。

    一個常見的模式是讓一個線程產生內容,另一個線程做一些有用的東西。 這被稱為生產者 - 消費者模式。 在這種情況下,對於誰或什么嘗試SetBar()以及嘗試GetBar()內容沒有混淆。

    暫無
    暫無

    聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

     
    粵ICP備18138465號  © 2020-2024 STACKOOM.COM