0

簡単にしましょう。通常、 update() は複数のスレッドによって実行されます。これが真になると、 if(!isSplit && users.size() >= Constants.SPLIT_THRESHOLD) split() 関数がセル化されているときに誰も update() メソッドを実行しないようにしたい。

public class Cell {
    private ConcurrentHashMap<Integer, User> users;
    private ConcurrentHashMap<Long, Cell> subCells;
    private boolean isSplit;
    private Lock splitLock;

    public Set<Integer> update(User user){

        //code executed by 1 thread
        if(!isSplit && users.size() >= Constants.SPLIT_THRESHOLD)
        {
            splitLock.lock();
            {
                try
            {
                    split();
                    isSplit = true;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                finally
                {
                    splitLock.unlock();
                }
            }
        }

        // code executed by multiple threads
        // on users hashmap
    }
    private void merge(){}
    private void split(){}
}
4

2 に答える 2

4

書き込み/更新のためにロックするときの一般的なパターンは、最初にロックを取得してから、(書き込み/更新によって変更された) 条件を確認してから書き込みます。

lock
if(x) {
    write/update
}
unlock

あなたが投稿したコードに類似しているこれとは対照的です:

if(x) {
    lock
    write/update
    unlock
}

x はスレッド 1 に対して true と評価できますが、スレッド 2 は書き込み/更新を実行し、x は false と評価されますが、スレッド 1 は既に条件内にあり、とにかく書き込み/更新を実行します。不合格。

UPDATE : 更新された質問への回答。

ReentrantReadWriteLockの javadoc を確認してください。

おそらく、split() メソッドを書き込みロック (1 つのスレッドのみが取得できる) で分離し、update メソッドの残りの部分を読み取りロック (書き込みロックを持っていない限り、複数のスレッドが取得できます) で分離する必要があります。

于 2013-08-29T14:57:40.713 に答える