-1

いくつかのコードをいくつかのグローバル変数で並列化します。ReentrantReadWriteLock を使用します。スレッドセーフにしたい変数ごとに ReentrantReadWriteLock の独自のインスタンスが 1 つ必要であることを正しく理解しましたか?

つまり、すべてのスレッドが項目をアタッチできる 2 つのリストがあり、すべてのスレッドがそのリストから項目を読み取ることがあります。その場合、次のようなものを実装します。

private static String[] globalVariables = null;
private static String[] processedItems = null;

private final ReentrantReadWriteLock globalVariablesLock = new ReentrantReadWriteLock();
private final Lock globalVariablesEeadLock  = globalVariablesLock .readLock();
private final Lock globalVariablesWriteLock = globalVariablesLock .writeLock();
private final ReentrantReadWriteLock processedItemsLock = new ReentrantReadWriteLock();
private final Lock processedItemsLockReadLock  = processedItemsLock .readLock();
private final Lock processedItemsLockWriteLock = processedItemsLock .writeLock();

データベース接続(プール)、ロガー、その他のリストなど、さらに多くの変数がある場合はどうでしょうか。

新しい ReentrantReadWriteLock を作成する必要がありますか、それとも何か不足していますか? インターネット上のサンプルは、1 つの変数のみを処理します。

前もって感謝します。

4

3 に答える 3

1

何を守ろうとしているのですか?

変数をロックすることを考えないでください。ロックの目的は、不変式を保護することです。不変条件とは、常に真でなければならないプログラムの状態について作成できるアサーションです。たとえば、「変数 A、B、および C の合計は常にゼロになる」などです。

その場合、A、B、および C に別々のロックを用意しても意味がありません。その特定の不変条件を保護する1 つのロックが必要です。A、B、または C を変更したいスレッドはそのロックをロックする必要があり、それらの合計がゼロであることに依存するスレッドは同じロックをロックする必要があります。

多くの場合、一部の不変条件を一時的に破ることなくスレッドを進行させることはできません。例えば、

A += 1;    //breaks the invariant
B -= 1;    //fixes it again.

同期がなければ、他のスレッドが A、B、および C をこれら 2 つのステートメントの間に調べて、不変式が壊れていることを発見する可能性があります。

同期あり:

private final Object zeroSumLock = new Object();

void bumpA() {
    synchronized(zeroSumLock) {
        A += 1;
        B -= 1;
    }
}

boolean verifySum() {
    synchronized(zeroSumLock) {
        return (A+B+C) == 0;
    }
}
于 2015-10-21T13:58:18.060 に答える
0

はい、Lockスレッドセーフ変数 (この場合は配列) ごとに 1 つ必要です。ただし、使用を検討してください

ArrayList<String> syncList = Collections.synchronizedList(new ArrayList<String>());

配列の代わりに。通常、ライブラリに委譲する方がはるかに優れています (この場合、同期だけでなく、配列のサイズ変更も行います)。もちろん、実行する前に、ライブラリが期待どおりに動作することを確認してください (この場合、@SashaSalauyou が指摘したように、同時に読み取ることができなくなります)。

于 2015-10-21T12:16:06.397 に答える
0

Map解決策の 1 つは、必要なすべてのアイテムをロックする immutable を作成することです。

final static Map<String, ReadWriteLock> locks = Collections.unmodifiableMap(
     new HashMap<String, ReadWriteLock>() {{
         put("globalVariables", new ReentrantReadWriteLock());
         put("processedItems",  new ReentrantReadWriteLock());
         // rest items
     }}
);

HashMap は によってラップされCollections.unmodifiableMap()ているため変更できないため、スレッドセーフになります。

次に、コードで:

Lock lo = locks.get("globalVariables").readLock();
lo.acquire();
try {
    // ...
} catch (Exception e) {
    // ...
} finally {
    lo.release();
}
于 2015-10-21T12:21:13.273 に答える