让我的资源经理成为无死锁的"

时间:2012-10-09 21:37:56

标签: java multithreading resources

我的程序有一个无死锁的条件。 ResourceManager为客户提供服务 (Set<ResourceNames, long ID>)  写/读(布尔值true / false)。 这是一种方法static long getLock(Set<String> resources, boolean operation)static void releaseLock(long ID)

所有资源都是1-1。如果资源用于写入,则该资源不适用于另一个目标。如果要读取,其他客户端只能读取,不写入。 资源名称是Strings.While ResourceManager不能为它必须在getlock()方法中阻塞的客户端处理资源,并在资源可用于客户端时返回。

getlock()方法使用资源,并创建一个ID,并且relaselock()方法从ID中解放资源。我的任务是编写ResourceManager,它将是无死锁的。

Client类为随机操作和资源创建k客户端,并启动它。那堂课是写的,但我看不出来。 我的任务是编写一个类,以及这两个方法。

- 问题是阻止客户端并返回! -DeadLock - 免费

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;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

我不知道如何使用当前的实现获得死锁,但是它存在许多多线程问题:

  • 获取锁时的非原子行为(例如,如果我尝试获取A的锁,然后尝试同时获取B和A的锁,那么这将失败,但随后尝试获取锁只是B也会失败,因为前面的操作对状态做了不正确的改变。)
  • 当它们不应该被获取时获取的锁(例如,为同一资源调用getLock()的2个线程都可以成功,因为检查资源是否被锁定以及实际将资源添加到集合之间的时间窗口。
  • 当2个线程同时尝试更新同一个非线程安全的集合时,
  • ConcurrentModificationException会被无法预测地抛出。

您可以通过同步某些方法来解决其中的一些问题,但是您需要仔细执行此操作以避免一方面出现死锁并另一方面使其成为并行性瓶颈。

答案 1 :(得分:1)

我建议您使用AtomicBoolean 而是在getLock方法中:



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


这将避免像Simon所说的锁定,并且您不需要使用同步方法。

另外,我会在方法的底部执行所有'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;