2017-02-03 7 views
0

Mapはスレッドxとyに書き込まれ、スレッドzで読み込まれます。java:同期ブロック内のループ内のprotoオブジェクト

スレッドX:

synchronized (map) { 
    map.put(0, protoObjX); // protoObjX is a protocol buffer object 
} 
//... 
synchronized (map) { 
    map.remove(0); 
} 

スレッドY:

synchronized (map) { 
    map.put(1, protoObjY); // protoObjY is a protocol buffer object 
} 
//... 
synchronized (map) { 
    map.remove(1); 
} 

スレッドZ:

synchronized (map) { 
    logger.info(map.values().size()); // prints 2 
    for (ProtoObjType obj: map.values()) { 
     logger.info(obj); // logger is a org.apache.log4j.Logger 
    } 
} 

のみprotoObjXまたはprotoObjYが印刷されています。どちらも決してありません。なぜこれが起こっていますか?

私がlogger.info(map.values());を1つずつ行うのではなく、代わりに行うと、機能します。 proto objの代わりにPOJOを使用すると、それは機能します。

+0

マップのどの実装を使用していますか?それはバグかもしれない。 –

答えて

0

protobufのためにこれが不正行為を起こす理由はありません。私は古典的な競争状態を嗅ぐ。これを試してみてくださいシングルスレッド。私はそれが意志100%確信している

map.put(0, protoObjX); // protoObjX is a protocol buffer object 
map.put(1, protoObjY); // protoObjY is a protocol buffer object 
for (ProtoObjType obj: map.values()) { 
    logger.info(obj); // logger is a org.apache.log4j.Logger 
} 

それが動作する場合は、あなたが働く場合とないものとの間にスレッドタイミング差であるかを把握する必要があります。 protobufオブジェクトがいくつかのネットワーク層から受け取られている間に、あなたは現場でPOJOをローカルでテストすると思う。

+0

両方の要素があるという事実を追加するのを忘れました。地図のサイズは2です。私の編集した質問を参照してください。 – lf215

+0

log4jの代わりに 'System.out.println'を使用してみてください。また、指定されていないtoString強制に依存するのではなく、反復されたすべてのProtoObjTypeから特定の文字列値を印刷してみてください。 –

+0

フィールドを取得しても確かに動作しますが、強制的にtostringを使用すると変なことがあります。 – lf215

関連する問題