繁体   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