yan*_*nko 2 java io multithreading synchronization
基本上,我有一个包含 2 个方法的类:一个将对象序列化为 XML 文件,另一个从 XML 读取对象。以下是恢复对象的方法中同步部分的示例:
public T restore(String from) throws Exception {
// variables declaration
synchronized (from) {
try {
decoder = new XMLDecoder(new BufferedInputStream(
new FileInputStream(from)));
restoredItem = decoder.readObject();
decoder.close();
} catch (Exception e) {
logger.warning("file not found or smth: " + from);
throw new Exception(e);
}
}
// try to cast it
}
Run Code Online (Sandbox Code Playgroud)
序列化对象时采用类似的方法。现在,当我创建一个单元测试时,它依次创建 10 个线程,每个线程尝试序列化并立即读取布尔值或字符串,它会失败,显示发生 ClassCastExceptions。这让我觉得我的序列化是错误的(在单线程环境中一切正常)。如果你一直和我在一起:),这里有两个我需要你帮助的问题:
1. 是的,可以在字符串上同步,但是您需要在字符串上同步。实习生()为了始终获得相同的对象
StringBuffer sb = new StringBuffer(); sb.append("a").append("b");
String a = new String(sb.toString());
String b = new String(sb.toString());
a == b; //false
a.equals(b); //true
a.intern() == b.intern(); //true
Run Code Online (Sandbox Code Playgroud)
由于您想在同一个监视器上同步,因此您需要 intern()。
2. 您可能不想在 String 上进行同步,因为它可能会在其他地方、您的代码内部、第 3 方或 JRE 中同步。如果我想保持同步,我会做的是创建一个 ID 类(它可能只包含字符串),覆盖 equals() 和 hashcode() 以匹配,将它放在一个 WeakHashMap 中,同时作为键和值(请参阅 IdentityHashMap 了解原因)并仅使用我从地图中获取的内容(sync map{ syncKey = map.get(new ID(from)); if syncKey==null create and put new key} sync{syncKey} )。
3. 再说一次,我将全部同步并使用 java.util.concurrent.locks.Lock 代替,在与上述相同的设置中,仅将锁附加到 ID。