3

複数のスレッドから同時にアクセスできるマップを持つシングルトンクラスがあります。誰かが以下のコードをチェックして、そのスレッドが安全かどうか教えてもらえますか?(注:ConcurrentHashMapを使用する予定はなく、printMapメソッドが呼び出されることはめったにありません。)

    public  class MySingleton{

      private Map<String,String>  cache = Collections.synchronizedMap(
new LinkedHashMap<String,String>());

      public String getValue(String key){
         return cache.get(key)
      }

      public void setValue(String key, String value){
         cache.put(key, value);
      }

      public void printMap(){
          synchronized(cache){

              for(Entry<String,String> entry: cache.entrySet()){
                    println('key: '+entry.getKey()+', value: ' + value);

               }
          }

      }
    }

私のテストは機能しています...しかし、このコードが「スレッドセーフ」と呼ばれるのに十分かどうか疑問です。

私が考えたポイント:

  1. 私はsynchronizedMapを使用しているので、readValueメソッドとputValueメソッドには「synchronized」ブロックは必要ありません。

  2. のjavadocは、各反復の前にMapインスタンスを同期する必要があると述べているため、printMapには同期ブロックが必要です。 http://download.oracle.com/javase/1.5.0/docs/api/java/util/Collections.html#synchronizedMap%28java.util.Map%29

どんな助けでも大歓迎です。

4

3 に答える 3

4

はい、大丈夫です。cache.put重要なのは、反復している間は、とにかく同期してしまうため、マップを変更することはできませcacheん。

個人的には、「通常の」ハッシュマップを使用し、3つの方法すべてから同じオブジェクト(マップまたはその他のもの)で同期することで、それを明示的にしたいと思いますが、得られたものは問題ないはずです。

(または、最初に使用することもできますConcurrentHashMap。少なくともそれを確認する価値があります。)

于 2011-04-13T12:16:14.823 に答える
0

はい、スレッドセーフです。キャッシュへの各アクセスは同期されます(getおよびsetの場合はsynchronizedMapによって、printMapの場合は明示的な同期ブロックによって)

于 2011-04-13T12:16:49.723 に答える
0

はい、このクラスはスレッドセーフです。

ただし、スレッドセーフクラスでさえ、安全な公開cacheを本当に安全に使用する必要があることに注意してください(安全な公開がなければ、他のスレッドが初期化されていない状態で表示できないことを保証するものはありませんnull

ただし、この場合、クラスを不変にすることで、安全な公開の必要性を排除できます(finalキーワードは、他のスレッドがで表示できないことを保証しnullますcache)。

private final Map<String,String>  cache = Collections.synchronizedMap( new LinkedHashMap<String,String>()); 
于 2011-04-13T12:19:02.267 に答える