简体   繁体   English

Java的。在多线程环境中序列化对象

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

I have an object whose internal mutable state is being constantly updated by one or more threads. 我有一个对象,其内部可变状态由一个或多个线程不断更新。 The object is synchronized, and the goal is to periodically save its state (via serialization) from yet another thread: 对象是同步的,目标是定期从另一个线程保存其状态(通过序列化):

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; 
    }
}

Questions: 问题:

  • Is serialization safe in this case? 在这种情况下序列化安全吗?
  • How does it work under the hood? 它是如何在引擎盖下工作的? That is to say, will the ObjectOutputStream performing the serialization block until no threads are any longer operating on Counter ? 也就是说, ObjectOutputStream执行序列化块直到没有线程再次在Counter运行?
  • What if Counter 's synchronization doesn't use the intrinsic lock, but some other lock? 如果Counter的同步不使用内部锁定,而是使用其他锁定怎么办?

Whenever it's necessary to modify the serialization of a class you have to implement the special private method void writeObject(ObjectOutputStream) . 每当需要修改类的序列化时,您必须实现特殊的私有方法void writeObject(ObjectOutputStream) The ObjectOutputStream uses this method instead of the default algorithm then. 然后, ObjectOutputStream使用此方法而不是默认算法。

In your case you want the serialization to be synchronized with the object. 在您的情况下,您希望序列化与对象同步。 So all you have to do is adding the synchronized keyword to the method. 所以你要做的就是将synchronized关键字添加到方法中。 You can still use the default implementation defaultWriteObject : 您仍然可以使用默认实现defaultWriteObject

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

It's not safe, but it is relatively easy to make it so: 它不安全,但它是相对容易的:

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

As you noticed, the object locked is arbitrary, so how would the serialisation mechnaism know how to obtain the relevant lock. 正如您所注意到的,锁定的对象是任意的,因此序列化机制如何知道如何获得相关的锁定。 Worse than that, the order of serialising and object graph is also quite arbitrary, so any attempt to lock would often lead to deadlocks. 更糟糕的是,序列化和对象图的顺序也很随意,因此任何锁定尝试都会导致死锁。 Even with the solution above, you are performing a complex operation within a lock, so be careful about deadlocks. 即使使用上面的解决方案,您也在锁内执行复杂操作,因此请注意死锁。

  • Is serialization safe in this case? 在这种情况下序列化安全吗?

No. As @Tom Hawtin says, you will need to perform your own locking to ensure that the object(s) are not changed while you are serializing them. 不。正如@Tom Hawtin所说,您需要执行自己的锁定,以确保在序列化对象时不会更改对象。

  • How does it work under the hood? 它是如何在引擎盖下工作的? That is to say, will the ObjectOutputStream performing the serialization block until no threads are any longer operating on Counter? 也就是说,ObjectOutputStream是否会执行序列化块直到没有线程再次在Counter上运行?

ObjectOutputStream does no locking under the hood. ObjectOutputStream没有锁定。 It is up to the application to do this, if it is necessary. 如果有必要,应由此应用程序执行此操作。

  • What if Counter's synchronization doesn't use the intrinsic lock, but some other lock? 如果Counter的同步不使用内部锁定,而是使用其他锁定怎么办?

Then your application will also need to use that other lock to lock out updates while serialization is happening. 然后,您的应用程序还需要使用该其他锁来锁定更新,同时进行序列化。

If the state that you are serializing simply consists of the state of one object with two fields, then lock contention and granularity should not be a problem. 如果您正在序列化的状态只包含一个具有两个字段的对象的状态,那么锁争用和粒度应该不是问题。 But if the object(s) are complicated, then lock contention could well be problematic, as could the problem of acquiring the locks without risking deadlock. 但是如果对象很复杂,那么锁争用可能会成为问题,因为获取锁的问题可能没有死锁的风险。 That scenario would require careful design. 那种情况需要仔细设计。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM