-1

私のプログラムには、デッドロックが発生しない条件があります。ResourceManager は、クライアントに (Set<ResourceNames, long ID>) 書き込み/読み取りを許可します (ブール値の true/false)。それはメソッド static long getLock(Set<String> resources, boolean operation) であり、 static void releaseLock(long ID).

すべてのリソースは 1-1 です。リソースが書き込みに使用されている場合、そのリソースは別のターゲットには適用されません。読み取りの場合、他のクライアントは読み取りのみを取得できますが、書き込みはできません。リソース名は Strings です。ResourceManager はクライアントのリソースを特定できませんが、getlock() メソッドでブロックし、リソースがクライアントで使用可能になったときに戻る必要があります。

getlock() メソッドはリソースをエンゲージして ID を作成し、relaselock() メソッドは ID からリソースを解放します。私の仕事は、ResourceManager を作成することであり、デッドロックが発生しません。

Client クラスは、ランダムな操作とリソース用に k 個のクライアントを作成し、これを開始します。そのクラスは書かれていますが、私はそれを見ることができません。私の仕事は、クラスとこれら 2 つのメソッドを作成することです。

- そして問題は、クライアントをブロックして返すことです! -デッドロック - 無料

package itself.probafeladat14;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Random;
import java.util.Set;

public class ResourceManager {

    protected static HashMap<String, Boolean> reservedResources = 
            new HashMap<String, Boolean>();
    protected static HashMap<Long, Set<String>> resourcesByID = 
            new HashMap<Long, Set<String>>();
    protected static LinkedList<Long> sequenceOfID =
            new LinkedList<Long>();



    public static void releaseLock(long ID) {
        boolean read = false;
        Set<String> resources = resourcesByID.remove(ID);
        sequenceOfID.remove(ID);

        for (String str : resources)
            if (reservedResources.containsKey(str)) {
                if (reservedResources.get(str) == true)
                    reservedResources.remove(str);
                else if (reservedResources.get(str) == false) {
                    for (long i : sequenceOfID)
                        if (resourcesByID.get(i).contains(str))
                            read = true;
                    if (!read)
                        reservedResources.remove(str);
                    read = false;
                }
            }
    }


    public static long getLock(Set<String> resources, boolean operation) throws ResourceNotAvaliableException {

        boolean isFree = true;
        boolean uniqueID = false;
        long ID = 0;

        for (String str : resources) {
            if (reservedResources.containsKey(str)) {
                if (reservedResources.get(str) ) {
                    isFree = false;
                }
                if (reservedResources.get(str) == false && 
                        operation == true) {
                    isFree = false;
                }
            }
        }

        if ( !isFree )
            throw new ResourceNotAvaliableException();
        else {
            for (String s : resources)
                if (!reservedResources.containsKey(s))
                    reservedResources.put(s, operation);
            while (!uniqueID) {
                ID = new Random().nextLong();
                if (!sequenceOfID.contains(ID))
                    uniqueID = true;
            }
            sequenceOfID.addLast(ID);
            resourcesByID.put(ID, resources);
            return ID;
        }
    }
}
4

2 に答える 2

1

現在の実装でデッドロックが発生する方法はわかりませんが、マルチスレッドの問題がいくつかあります。

  • ロックを取得したときの非アトミックな動作 (たとえば、A のロックを取得しようとしてから、B と A のロックを同時に取得しようとすると、これは失敗しますが、B だけのロックを取得しようとすると、前の操作で状態が誤って変更されたため、失敗することもあります)。
  • ロックが取得されるべきではない場合 (たとえばgetLock()、同じリソースを呼び出す 2 つのスレッドは、リソースがロックされているかどうかを確認してから実際にリソースをセットに追加するまでの時間枠のために、両方とも成功する可能性があります。
  • ConcurrentModificationException2 つのスレッドが同じ非スレッド セーフ コレクションを同時に更新しようとすると、予期せずスローされます。

これらの問題のいくつかは、特定のメソッドを同期することで解決できますが、一方ではデッドロックを回避し、他方では並列処理のボトルネックにならないように慎重に行う必要があります。

于 2012-10-09T22:26:39.773 に答える
1

代わりに getLock メソッドでAtomicBooleanを使用することをお勧めします。



      if (!reservedResources.containsKey(s)) {
        reservedResources.get(s).set(operation);
      }


これにより、サイモンが言うようにロックが回避され、同期メソッドを使用する必要がなくなります。

また、すべての 'isFree' ロジックをメソッドの最後に実行します。言い換えると:




     for (String s : resources) {
         if (reservedResources.containsKey(s)) {
             if (reservedResources.get(s).get()) {
                 throw new ResourceNotAvaliableException();
             }
             if (!reservedResources.get(s).get() && operation == true) {
                 throw new ResourceNotAvaliableException()
             }
         }
    }
    for (String s : resources) {
        if (!reservedResources.containsKey(s))
            reservedResources.put(s, operation);
    }
    while (!uniqueID) {
        ID = new Random().nextLong();
        if (!sequenceOfID.contains(ID))
            uniqueID = true;
    }
    sequenceOfID.addLast(ID);
    resourcesByID.put(ID, resources);
    return ID;


于 2012-10-10T01:50:26.503 に答える