11

私はマルチスレッド環境に少し慣れていないので、次の状況に最適なソリューションを考え出そうとしています。

私はデータベースからデータを1日1回午前中に読み取り、そのデータをシングルトンオブジェクトのHashMapに格納します。日中のDB変更が発生した場合にのみ呼び出されるsetterメソッドがあります(これは1日に0〜2回発生します)。

マップ内の要素を返すゲッターもあり、このメソッドは1日に数百回呼び出されます。

HashMapを空にして再作成しているときにゲッターが呼び出され、空の/不正な形式のリストで要素を見つけようとする場合が心配です。これらのメソッドを同期させると、2人のリーダーが同時にゲッターにアクセスできなくなり、パフォーマンスのボトルネックになる可能性があります。書き込みはめったに発生しないので、パフォーマンスの低下をあまり受けたくありません。ReentrantReadWriteLockを使用する場合、書き込みロックが解除されるまで、ゲッターを呼び出す人にキューを強制しますか?複数のリーダーが同時にゲッターにアクセスできるようにしますか?一度に1人のライターのみを強制しますか?

これをコーディングするのは...

private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Lock read = readWriteLock.readLock();
private final Lock write = readWriteLock.writeLock();

public HashMap getter(String a) {
    read.lock();
    try {
        return myStuff_.get(a);            
    } finally {
        read.unlock();
    }
}

public void setter() 
{
    write.lock();
    try {
        myStuff_ = // my logic
     } finally {
          write.unlock();
    }
}
4

3 に答える 3

15

これを(ロックを使用せずに)実現する別の方法は、コピーオンライトパターンです。あなたが頻繁に書かないとき、それはうまくいきます。アイデアは、フィールド自体をコピーして置き換えることです。次のようになります。

private volatile Map<String,HashMap> myStuff_ = new HashMap<String,HashMap>();

public HashMap getter(String a) {
    return myStuff_.get(a);
}

public synchronized void setter() {
    // create a copy from the original
    Map<String,HashMap> copy = new HashMap<String,HashMap>(myStuff_);
    // populate the copy
    // replace copy with the original
    myStuff_ = copy;
}

これにより、リーダーは完全に同時実行され、リーダーが支払う唯一のペナルティはmyStuff_での揮発性の読み取りです(これはごくわずかです)。ライターは、相互排除を確実にするために同期されます。

于 2011-05-13T05:22:05.327 に答える
2

はい、書き込みロックがスレッドによって保持されている場合、getter メソッドにアクセスする他のスレッドは読み取りロックを取得できないため、ブロックされます。だからあなたはここで大丈夫です。詳細については、ReentrantReadWriteLock の JavaDoc を参照してください - http://download.oracle.com/javase/6/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html

于 2011-05-12T18:33:16.500 に答える
0

一日の始まりにこのことを開始します... 1 日に 0 ~ 2 回更新し、1 日に何百回も読んでいます。読み取りにかかると仮定すると、たとえば、1 日 8 時間 (28800 秒) で 1 秒 (非常に長い時間) かかるとすると、読み取り負荷は非常に低くなります。ReentrantReadWriteLock のドキュメントを見ると、モードを「調整」して「公平」にすることができます。これは、最も長く待機しているスレッドがロックを取得することを意味します。したがって、公平に設定すれば、書き込みスレッドが枯渇することはないと思います。

参考文献

ReentrantReadWriteLock

于 2011-05-12T18:38:41.023 に答える