两个线程,其中一个线程对某个实例进行功能新操作,另一个线程将同一个实例序列化后通过网络发送。如何保证线程安全。

----------------------------------------------------------------------------------------

网上这方面的资料只有寥寥几篇。

先贴上这个靠谱点的

 

http://www.zx2010.com/question/java-serialization-objects-multithreaded-environment.asp

 

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:
  1. Is serialization safe in this case?
  2. 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?
  3. What if Counter's synchronization doesn't use the intrinsic lock, but some other lock?
Answers:

 

  • 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.
  • 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 does no locking under the hood. 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?
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.
--------------------------------------------------------------
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.

下面贴几个不大靠谱的

这个不大明白啥意思

 

http://www.zx2010.com/question/java-object-serialization-thread-safe.asp

 

I am writing highly concurrent application, which is extensively modifies objects of MyClass. The class is composed of several fields. My question is how to prevent modifications of particular object during its serialization by another thread? Regards, Matt
 

 

 By synchronizing both the methods which serialize and modify the object state.

-----------------------------------------------------------------------

 

Why modify MyClass? A better approach (and much easier to deal with concurrently) is to create new immutable versions of your state object and CAS them with an AtomicReference when updating. Eg:

 

final class MyClass {
  
final int age;
  
final String name;
  
final String address;

  MyClass(
int age, String name, String address) {...}

  MyClass setNameAndAddress(String name, String address) {
return new MyClass(age, name, address);}
}

 

Then serialization is not a problem as you are dealing with an immutable object. Your stored reference can only change from one valid state to another, and multiple updates can be performed atomically.

 

 

 又是一个不靠谱的

 

http://stackoverflow.com/questions/3910595/is-java-util-vector-serialization-thread-safe

 

 

 

I know the Vector class is thread-safe for adding and removing elements [reference].

If I serialize a Vector using an ObjectOutputStream am I guaranteed a consistent (and non-corrupt) state when I deserialize it even if other threads are adding and removing objects during the seralization?

 

The writeObject() method is synchronized. But there's nothing in the Javadoc that guarantees that unless it's implied by the statement 'Vector is synchronized'.

Note that the readObject() method doesn't need to be synchronized, as the object isn't accessible to anybody until readObject() returns.

 

 ***************************************************************************************************************

****************************************************************************************************************

《Effective Java中文版第2版》P264:

无论你是否使用默认的序列化形式,如果在读取整个对象状态的任何其他方法上强制任何同步,则也必须在对象序列化上强制这种同步。因此,如果你有一个线程安全的对象,它通过同步每个方法实现了它的线程安全,并且你选择使用默认的序列化形式,就要使用下列的writeObject方法:

// writeObject for synchronized class with default serialized form
private synchronized void writeObject(ObjectOutputStream s) throws IOException {
    s.defaultWriteObject();
}

 如果你把同步放在writeObject方法中,就必须确保它遵守与其他动作相同的锁排列(lock-ordering)约束条件,否则就有遭遇资源排列(resource-ordering)死锁的危险【Goetz06,10.1.5】。

------------------------------------

至于readObject,书中没提, 我想应该不需要同步,原因正是因为书中反复提到的一句话:readObject方法实际上相当于另一个公有的构造器,如同其他的构造器一样。...不严格地说,readObject是一个“用字节流作为唯一参数”的构造器。嗯,上面提到的这句话还是有点道理的:

Note that the readObject() method doesn't need to be synchronized, as the object isn't accessible to anybody until readObject() returns.
嗯,这个问题到这里就算解决了吧,《Effective Java》这本书还是比较令人信服的吧!

 

 

 

 

 

 

posted on 2011-09-10 21:02  网络大豆  阅读(1000)  评论(0编辑  收藏  举报