16.4 Design a class which provides a lock only if there are no possible deadlocks.

有很多方法可以避免死锁的发生,一个常用的方法是列出所需要的锁,然后判断锁上这些锁后会不会发生死锁,比如有如下的锁的顺序:

A = {1, 2, 3, 4}

B = {1, 3, 5}

C = {7, 5, 9, 2}

这是有可能产生死锁的,比如当A锁上2等待3,当B锁上3等待5,当C锁上5等待2,我们可以将其看做图,2连上3,3连上5,5连上2,那么就会有环。一条边(w,v)表示锁上v后马上锁w,那么上述里子的图中的边为(1, 2), (2, 3), (3, 4), (1, 3), (3, 5), (7, 5), (5, 9), (9, 2)。那么我们在检测是否有死锁的情况就是要找图中是否存在环,我们可以用DFS来搜索所有的相连的部分,我们用DFS需要标记点的状态,我们首先定义个LockFactory类,用来保存锁的序列,比如上面的A,B,C,然后对于每一个锁序列,我们先将所有的锁都链起来,然后标记为false,然后用DFS判断是否有环,如果有环,则断开当前锁序列之间的所有连接,参见代码如下;

import java.util.Hashtable;
import java.util.LinkedList;
import java.util.concurrent.locks.Lock; public class LockFactory {
private static LockFactory instance;
private int numberOfLocks = 5;
private LockNode[] locks;
private Hashtable<Integer, LinkedList<LockNode>> lockOrder; private LockFactory(int count) {
numberOfLocks = count;
locks = new LockNode[numberOfLocks];
lockOrder = new Hashtable<Integer, LinkedList<LockNode>>();
for (int i = 0; i < numberOfLocks; ++i) {
locks[i] = new LockNode(i, count);
}
} public static LockFactory getInstance() {
return instance;
} public static LockFactory initialize(int count) {
if (instance == null) {
instance = new LockFactory(count);
}
return instance;
} public boolean hasCycle(Hashtable<Integer, Boolean> touchedNodes, int[] resourcesInOrder) {
for (int resource : resourcesInOrder) {
if (touchedNodes.get(resource) == false) {
LockNode n = locks[resource];
if (n.hasCycle(touchedNodes)) {
return true;
}
}
}
return false;
} public boolean declare(int ownerId, int[] resourcesInOrder) {
Hashtable<Integer, Boolean> touchedNodes = new Hashtable<Integer, Boolean>();
int index = 1;
touchedNodes.put(resourcesInOrder[0], false);
for (index = 1; index < resourcesInOrder.length; ++index) {
LockNode pre = locks[resourcesInOrder[index - 1]];
LockNode cur = locks[resourcesInOrder[index]];
pre.joinTo(cur);
touchedNodes.put(resourcesInOrder[index], false);
}
if (hasCycle(touchedNodes, resourcesInOrder)) {
for (int j = 1; j < resourcesInOrder.length; ++j) {
LockNode p = locks[resourcesInOrder[j - 1]];
LockNode c = locks[resourcesInOrder[j]];
p.remove(c);
}
return false;
}
LinkedList<LockNode> list = new LinkedList<LockNode>();
for (int i = 0; i < resourcesInOrder.length; ++i) {
LockNode resource = locks[resourcesInOrder[i]];
list.add(resource);
}
lockOrder.put(ownerId, list);
return true;
} public Lock getLock(int ownerId, int resourceId) {
LinkedList<LockNode> list = lockOrder.get(ownerId);
if (list == null) return null;
LockNode head = list.getFirst();
if (head.getId() == resourceId) {
list.removeFirst();
return head.getLock();
}
return null;
}
} import java.util.ArrayList;
import java.util.Hashtable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class LockNode {
public enum VisitState {
FRESH, VISITING, VISITED
};
private ArrayList<LockNode> children;
private int lockId;
private Lock lock;
private int maxLocks; public LockNode(int id, int max) {
lockId = id;
children = new ArrayList<LockNode>();
maxLocks = max;
} public void joinTo(LockNode node) {
children.add(node);
} public void remove(LockNode node) {
children.remove(node);
} public boolean hasCycle(Hashtable<Integer, Boolean> touchedNodes) {
VisitState[] visited = new VisitState[maxLocks];
for (int i = 0; i < maxLocks; ++i) {
visited[i] = VisitState.FRESH;
}
return hasCycle(visited, touchedNodes);
} public boolean hasCycle(VisitState[] visited, Hashtable<Integer, Boolean> touchedNodes) {
if (touchedNodes.containsKey(lockId)) {
touchedNodes.put(lockId, true);
}
if (visited[lockId] == VisitState.VISITING) {
return true;
} else if (visited[lockId] == VisitState.FRESH) {
visited[lockId] = VisitState.VISITING;
for (LockNode n : children) {
if (n.hasCycle(visited, touchedNodes)) {
return true;
}
}
visited[lockId] = VisitState.VISITED;
}
return false;
} public Lock getLock() {
if (lock == null) {
lock = new ReentrantLock();
}
return lock;
} public int getId() {
return lockId;
}
} public class j {
public static void main(String[] args) {
int[] res1 = {1, 2, 3, 4};
int[] res2 = {1, 5, 4, 1};
int[] res3 = {1, 4, 5};
LockFactory.initialize(10); LockFactory lf = LockFactory.getInstance();
System.out.println(lf.declare(1, res1));
System.out.println(lf.declare(2, res2));
System.out.println(lf.declare(3, res3)); System.out.println(lf.getLock(1, 1));
System.out.println(lf.getLock(1, 2));
System.out.println(lf.getLock(1, 3));
System.out.println(lf.getLock(1, 4));
System.out.println(lf.getLock(2, 1));
System.out.println(lf.getLock(2, 5));
System.out.println(lf.getLock(2, 4));
System.out.println(lf.getLock(3, 1));
System.out.println(lf.getLock(3, 4));
System.out.println(lf.getLock(3, 5));
}
}

CareerCup All in One 题目汇总

[CareerCup] 16.4 A Lock Without Deadlocks 无死锁的锁的更多相关文章

  1. 转:synchronized和LOCK的实现原理---深入JVM锁机制

    JVM底层又是如何实现synchronized的? 目前在Java中存在两种锁机制:synchronized和Lock,Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug ...

  2. 015-线程同步-synchronized几种加锁方式、Java对象头和Monitor、Mutex Lock、JDK1.6对synchronized锁的优化实现

    一.synchronized概述基本使用 为确保共享变量不会出现并发问题,通常会对修改共享变量的代码块用synchronized加锁,确保同一时刻只有一个线程在修改共享变量,从而避免并发问题. syn ...

  3. 16、Java并发性和多线程-死锁

    以下内容转自http://ifeve.com/deadlock/: 死锁是两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁.死锁通常发生在多个线程同时但以不同的顺序请求同一组锁的时候. 例如, ...

  4. Lock方法是用于数据库的锁机制,

    Lock方法是用于数据库的锁机制,如果在查询或者执行操作的时候使用: lock(true); 复制代码   就会自动在生成的SQL语句最后加上 FOR UPDATE或者FOR UPDATE NOWAI ...

  5. [CareerCup] 16.3 Dining Philosophers 哲学家聚餐问题

    16.3 In the famous dining philosophers problem, a bunch of philosophers are sitting around a circula ...

  6. [CareerCup] 16.5 Semphore 信号旗

    16.5 Suppose we have the following code:public class Foo { public Foo() { . . . } public void first( ...

  7. [CareerCup] 16.6 Synchronized Method 同步方法

    16.6 You are given a class with synchronized method A and a normal method B. If you have two threads ...

  8. [CareerCup] 16.2 Measure Time in a Context Switch 测量上下文转换的时间

    16.2 How would you measure the time spent in a context switch? 上下文转换发生在两个进程之间,比如让一个等待进程进入执行和让一个运行进程进 ...

  9. [CareerCup] 16.1 Thread and Process 线程和进程

    16.1 What's the difference between a thread and a process? 进程Process是程序执行时的一个实例.一个进程是被分配系统资源的独立单元,每个 ...

随机推荐

  1. Sublime Text3 配置Node.js运行命令

    ­ 在Sublime Text中可以很容易配置新的编译运行命令,下面的截图是汉化版的中文菜单,英文菜单请直接对照. 首先需要在本地安装Node,默认的Node会加入到系统的环境变量,这样执行Node命 ...

  2. 协处理器,王明学learn

    协处理器 协处理器用于执行特定的处理任务,如:数学协处理器可以控制数字处理,以减轻处理器的负担.ARM可支持多达16个协处理器,其中CP15是最重要的一个. CP15提供16组寄存器 通过提供的16组 ...

  3. Flash Media Server 4.0 破解 注册

    Adobe Flash Media Interactive Server 3.5s/n:1373-5047-2985-0514-5175-0098 s/n: 1373-5632-4666-9521-8 ...

  4. hdu 1063(java写高精度)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1063 思路:最近刚学了java,然后就迫不及待想试试java写大数的好处了,呵呵,果然是很方便啊! i ...

  5. PrograssBar的setIndeterminateDrawable不起作用

    是设置绘制不显示进度的进度条的Drawable对象 使用中发现,在xml中设置IndeterminateDrawable可以正常使用,但是如果需要在代码中更换图片使用setIndeterminateD ...

  6. T-SQL 使用WITH高效分页

    一.WITH AS 含义     WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到.有的时候, ...

  7. loadrunner中切割strtok字符串

    http://blog.sina.com.cn/s/blog_7ee076050102vamg.html http://www.cnblogs.com/lixiaohui-ambition/archi ...

  8. JAVA Day5

                                         数组   1.数组是一组变量的集合,存储“相同数据类型”的一组数据: 连续的空间. 2.声明一个变量就是在内存空间划出一块合适 ...

  9. SpringMyBatis解析2-SqlSessionFactoryBean

    通过分析整合示例中的配置文件,我们可以知道配置的bean其实是成树状结构的,而在树的最顶层是类型为org.mybatis.spring.SqlSessionFactoryBean的bean,它将其他相 ...

  10. DP ZOJ 2745 01-K Code

    题目传送门 题意:要求任意连续子序列中0和1的数量差不超过k的方案数 分析:想好状态其实不难.dp[i][j][k]表示考虑前i长度,后缀中最大的 sum(0) - sum(1) = j, sum ( ...