-1

我的程序有一个条件是无死锁的。ResourceManager 允许客户端 (Set<ResourceNames, long ID>) 写入/读取(布尔值 true/false)。那是一种方法 static long getLock(Set<String> resources, boolean operation)static void releaseLock(long ID)

所有资源都是1-1。如果资源正在写入,则该资源不适用于另一个目标。如果用于读取,其他客户端只能读取,不能写入。资源名称是字符串。虽然 ResourceManager 不能为客户端提供资源,但它必须在 getlock() 方法中阻塞并在资源可供客户端使用时返回。

getlock()方法是获取资源,并创建一个ID,relaselock()方法是从ID中解放资源。我的任务是编写 ResourceManager,它不会死锁。

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

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

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 个线程都可以成功,因为在检查您的资源是否被锁定和实际将资源添加到集合之间存在时间窗口。
  • ConcurrentModificationException当 2 个线程尝试同时更新同一个非线程安全集合时,会意外抛出。

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

于 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 回答