簡體   English   中英

Java的。在多線程環境中序列化對象

[英]Java. Serialization of objects in a multithreaded environment

我有一個對象,其內部可變狀態由一個或多個線程不斷更新。 對象是同步的,目標是定期從另一個線程保存其狀態(通過序列化):

public class Counter implements Serializable {
    private int dogCount;
    private int catCount;

    public synchronized void updateFromDogThread( int count ) { 
        dogCount = count; 
    }

    public synchronized void updateFromCatThread( int count ) { 
        catCount = count; 
    }
}

問題:

  • 在這種情況下序列化安全嗎?
  • 它是如何在引擎蓋下工作的? 也就是說, ObjectOutputStream執行序列化塊直到沒有線程再次在Counter運行?
  • 如果Counter的同步不使用內部鎖定,而是使用其他鎖定怎么辦?

每當需要修改類的序列化時,您必須實現特殊的私有方法void writeObject(ObjectOutputStream) 然后, ObjectOutputStream使用此方法而不是默認算法。

在您的情況下,您希望序列化與對象同步。 所以你要做的就是將synchronized關鍵字添加到方法中。 您仍然可以使用默認實現defaultWriteObject

private synchronized void writeObject(ObjectOutputStream out) throws IOException {
    out.defaultWriteObject();
}

它不安全,但它是相對容易的:

synchronized (counter) {
    out.writeObject(counter);
}

正如您所注意到的,鎖定的對象是任意的,因此序列化機制如何知道如何獲得相關的鎖定。 更糟糕的是,序列化和對象圖的順序也很隨意,因此任何鎖定嘗試都會導致死鎖。 即使使用上面的解決方案,您也在鎖內執行復雜操作,因此請注意死鎖。

  • 在這種情況下序列化安全嗎?

不。正如@Tom Hawtin所說,您需要執行自己的鎖定,以確保在序列化對象時不會更改對象。

  • 它是如何在引擎蓋下工作的? 也就是說,ObjectOutputStream是否會執行序列化塊直到沒有線程再次在Counter上運行?

ObjectOutputStream沒有鎖定。 如果有必要,應由此應用程序執行此操作。

  • 如果Counter的同步不使用內部鎖定,而是使用其他鎖定怎么辦?

然后,您的應用程序還需要使用該其他鎖來鎖定更新,同時進行序列化。

如果您正在序列化的狀態只包含一個具有兩個字段的對象的狀態,那么鎖爭用和粒度應該不是問題。 但是如果對象很復雜,那么鎖爭用可能會成為問題,因為獲取鎖的問題可能沒有死鎖的風險。 那種情況需要仔細設計。

暫無
暫無

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

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