[英]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.