- 浏览: 331207 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (212)
- spring (21)
- design pattern(java) (12)
- linux-shell (28)
- java-thread (20)
- java-collection (6)
- java-reflect (9)
- mysql (11)
- java-io (7)
- java-util&lang&io (3)
- algorithm (3)
- interview (2)
- tools-eclipse (2)
- tools-maven (1)
- web-script (1)
- java组建 (13)
- 博客收藏 (1)
- 架构设计与实践 (10)
- active-mq (6)
- java-jvm&性能&原理 (27)
- tomcat (2)
- flume (1)
- serialization (2)
- git (1)
- cache&redis (8)
- guava (1)
- zookeeper (3)
- socket&tcp&udp&http (6)
- test (1)
最新评论
-
bbls:
有用有用有用
java-jvm-jstack-(监视器和锁的概念) -
王新春:
小侠有点帅哦 写道此流怎么关闭新春这个实现 可以不关闭的,哈哈 ...
源码剖析之java.io.ByteArrayOutputStream -
小侠有点帅哦:
此流怎么关闭新春
源码剖析之java.io.ByteArrayOutputStream -
cumt168:
写的很好为什么初始化参数,年轻代-Xmn10M def new ...
jvm之内存申请过程分析 -
ronin47:
应该是跟共享域名思路差不多,根据cookie的key作判断
跨域:一种通过服务端解决跨域的实现
java的多线程机制非常强大。其中死锁会导致程序无止境的等待,影响系统的正常运行,并且不是发生时立即被发现,一旦被发现定然是,系统出现了明显的功能性无法正常运行,甚至是系统崩溃。
下面我们讨论死锁的成因以及死锁的检测方法。
1、首先是系统运行时线程和锁之间的关系:
第一种情况:lock等待持有他们的thread将其释放。这些lock是由thread所持有,即thread获得了lock,其他的thread不能再获取到lock。
第二种情况:thread等待获取lock。如果此lock被其他的thead占用,那么此thread便只有等待其他thread将其释放。
2、死锁的产生
最简单的死锁产生的形式是:thread1 已经获取lock1,然后再去获取lock2,如果此时有thread2 已经获取了lock2 ,并且同时去获取lock1,那么就会发生死锁。
稍复杂的死锁的形式:
thread1:已经获得lock1
thread2:已经获得lock2,lock3。希望获得lock1
thread3:已经获得lock4。希望获得lock2
如果此时thread1 有需要获取到lock4,那么就可能会产生死锁。
3、死锁产生原因的分析:
从死锁的产生上,大家可以考虑到:如果将thread1 当成根节点,lock1是其子节点,thread2 是lock1的子节点,lock2,lock3 是thread2的子节点,同理:thread3 是lock2 的子节点,lock4 是thread3的子节点。如此可以看出thread与其相关的锁就是一个树结构,最上层是当前thread,其下是thread与lock交叉的分层。此树反应了一个thread所拥有的所有lock,然后是所有正在等待这些lock上thread,如此表示下去无论是直接还是间接,此树上的每个lock都在等待根thread最终将其释放,如此如果此thread需要对某个lock hard wait,它就不能在此树上,如此会产生一个循环,也就是死锁的成因。
4、下面的代码是实现了一个死锁检测的类,当产生死锁时抛出死锁异常。
注意:所有的锁的获取必须是lock形式,如果有synchrensed的锁形式,将不能被检测到。
下面这个例子展示了如何简单的检测到一个死锁。(当然效率是相当的低)
以上代码是:java Thread 第三版 第六章的代码,详细请查看原始代码
下面我们讨论死锁的成因以及死锁的检测方法。
1、首先是系统运行时线程和锁之间的关系:
第一种情况:lock等待持有他们的thread将其释放。这些lock是由thread所持有,即thread获得了lock,其他的thread不能再获取到lock。
第二种情况:thread等待获取lock。如果此lock被其他的thead占用,那么此thread便只有等待其他thread将其释放。
2、死锁的产生
最简单的死锁产生的形式是:thread1 已经获取lock1,然后再去获取lock2,如果此时有thread2 已经获取了lock2 ,并且同时去获取lock1,那么就会发生死锁。
稍复杂的死锁的形式:
thread1:已经获得lock1
thread2:已经获得lock2,lock3。希望获得lock1
thread3:已经获得lock4。希望获得lock2
如果此时thread1 有需要获取到lock4,那么就可能会产生死锁。
3、死锁产生原因的分析:
从死锁的产生上,大家可以考虑到:如果将thread1 当成根节点,lock1是其子节点,thread2 是lock1的子节点,lock2,lock3 是thread2的子节点,同理:thread3 是lock2 的子节点,lock4 是thread3的子节点。如此可以看出thread与其相关的锁就是一个树结构,最上层是当前thread,其下是thread与lock交叉的分层。此树反应了一个thread所拥有的所有lock,然后是所有正在等待这些lock上thread,如此表示下去无论是直接还是间接,此树上的每个lock都在等待根thread最终将其释放,如此如果此thread需要对某个lock hard wait,它就不能在此树上,如此会产生一个循环,也就是死锁的成因。
4、下面的代码是实现了一个死锁检测的类,当产生死锁时抛出死锁异常。
注意:所有的锁的获取必须是lock形式,如果有synchrensed的锁形式,将不能被检测到。
下面这个例子展示了如何简单的检测到一个死锁。(当然效率是相当的低)
import java.util.*; import java.util.concurrent.*; import java.util.concurrent.locks.*; // // This is a very very slow implementation of a ReentrantLock class and is not for // everyday usage. The purpose of this class is to test for deadlocks. The lock() // method now throws a DeadlockDetectedException, if a deadlock occurs. // public class DeadlockDetectingLock extends ReentrantLock { /** * */ private static final long serialVersionUID = 1L; // List of deadlock detecting locks. // This array is not thread safe, and must be externally synchronized // by the class lock. Hence, it should only be called by static // methods. private static List<DeadlockDetectingLock> deadlockLocksRegistry = new ArrayList<DeadlockDetectingLock>(); private static synchronized void registerLock(DeadlockDetectingLock ddl) { if (!deadlockLocksRegistry.contains(ddl)){ deadlockLocksRegistry.add(ddl); } } private static synchronized void unregisterLock(DeadlockDetectingLock ddl) { if (deadlockLocksRegistry.contains(ddl)){ deadlockLocksRegistry.remove(ddl); } } // List of threads hard waiting for this lock. // This array is not thread safe, and must be externally synchronized // by the class lock. Hence, it should only be called by static // methods. private List<Thread> hardwaitingThreads = new ArrayList<Thread>(); private static synchronized void markAsHardwait(List<Thread> l, Thread t) { if (!l.contains(t)) { l.add(t); } } private static synchronized void freeIfHardwait(List<Thread> l, Thread t) { if (l.contains(t)) { l.remove(t); } } // // Deadlock checking methods // // Given a thread, return all locks that are already owned // Must own class lock prior to calling this method private static Iterator<DeadlockDetectingLock> getAllLocksOwned(Thread t) { DeadlockDetectingLock current; ArrayList<DeadlockDetectingLock> results = new ArrayList<DeadlockDetectingLock>(); Iterator<DeadlockDetectingLock> itr = deadlockLocksRegistry.iterator(); while (itr.hasNext()) { current = (DeadlockDetectingLock) itr.next(); if (current.getOwner() == t) { results.add(current); } } return results.iterator(); } // Given a lock, return all threads that are hard waiting for the lock // Must own class lock prior to calling this method private static Iterator<Thread> getAllThreadsHardwaiting(DeadlockDetectingLock l) { return l.hardwaitingThreads.iterator(); } // Check to see if a thread can perform a hard wait on a lock private static synchronized boolean canThreadWaitOnLock(Thread t, DeadlockDetectingLock l) { //先获取t已经获取的lock锁list Iterator<DeadlockDetectingLock> locksOwned = getAllLocksOwned(t); while (locksOwned.hasNext()) { DeadlockDetectingLock current = locksOwned.next(); // Thread can't wait if lock is already owned. This is the end condition // for the recursive algorithm -- as the initial condition should be // already tested for. // t 获取 l 锁,如果此锁已经被需要获得l锁的线程获取,那么就是产生死锁的条件 if (current == l) return false; //获取(等待获取当前线程已经获得的current锁)的线程组 Iterator<Thread> waitingThreads = getAllThreadsHardwaiting(current); while (waitingThreads.hasNext()) { Thread otherthread = (Thread) waitingThreads.next(); // In order for the thread to safely wait on the lock, it can't // own any locks that have waiting threads that already owns // lock. etc. etc. etc. recursively etc. if (!canThreadWaitOnLock(otherthread, l)) { return false; } } } return true; } // // Core Constructors // public DeadlockDetectingLock() { this(false, false); } public DeadlockDetectingLock(boolean fair) { this(fair, false); } private boolean debugging; public DeadlockDetectingLock(boolean fair, boolean debug) { super(fair); debugging = debug; registerLock(this); } // // Core Methods // public void lock() { // Note: Owner can't change if current thread is owner. It is // not guaranteed otherwise. Other owners can change due to // condition variables. //当前线程是否获得当前锁 if (isHeldByCurrentThread()) { if (debugging){ System.out.println("Already Own Lock"); } super.lock(); //把当前线程从 wait list(无限等待获取该锁的线程列表)中移除,因为该线程已经获得该锁 freeIfHardwait(hardwaitingThreads, Thread.currentThread()); return; } // Note: The wait list must be marked before it is tested because // there is a race condition between lock() method calls. //如果当前线程没有获得当前锁,那么把当前线程加入到 wait list(无限等待获取该锁的线程列表) markAsHardwait(hardwaitingThreads, Thread.currentThread()); //测试当前线程能否获取this当前锁 if (canThreadWaitOnLock(Thread.currentThread(), this)) { if (debugging) { System.out.println("Waiting For Lock"); } super.lock(); freeIfHardwait(hardwaitingThreads, Thread.currentThread()); if (debugging) { System.out.println("Got New Lock"); } } else { throw new DeadlockDetectedException("DEADLOCK"); } } // // Note: It is debatable whether this is a hard or soft wait. Even if // interruption is common, we don't know if the interrupting thread // is also involved in the deadlock. As a compromise, we'll just // not allow interrupts. This method is disabled. public void lockInterruptibly() throws InterruptedException { lock(); } // // Note: It is not necessary to override the tryLock() methods. These // methods perform a soft wait -- there is a limit to the wait. It // not possible to deadlock when locks are not waiting indefinitely. // // Note 1: Deadlocks are possible with any hard wait -- this includes // the reacquitition of the lock upon return from an await() method. // As such, condition variables will mark for the future hard // wait, prior to releasing the lock. // Note 2: There is no need to check for deadlock on this end because // a deadlock can be created whether the condition variable owns the // lock or is reacquiring it. Since we are marking *before* giving // up ownership, the deadlock will be detected on the lock() side // first. It is not possible to create a new deadlock just by releasing // locks. public class DeadlockDetectingCondition implements Condition { Condition embedded; protected DeadlockDetectingCondition(ReentrantLock lock, Condition embedded) { this.embedded = embedded; } // Note: The algorithm can detect a deadlock condition if the thead is // either waiting for or already owns the lock, or both. This is why // we have to mark for waiting *before* giving up the lock. public void await() throws InterruptedException { try { markAsHardwait(hardwaitingThreads, Thread.currentThread()); embedded.await(); } finally { freeIfHardwait(hardwaitingThreads, Thread.currentThread()); } } public void awaitUninterruptibly() { markAsHardwait(hardwaitingThreads, Thread.currentThread()); embedded.awaitUninterruptibly(); freeIfHardwait(hardwaitingThreads, Thread.currentThread()); } public long awaitNanos(long nanosTimeout) throws InterruptedException { try { markAsHardwait(hardwaitingThreads, Thread.currentThread()); return embedded.awaitNanos(nanosTimeout); } finally { freeIfHardwait(hardwaitingThreads, Thread.currentThread()); } } public boolean await(long time, TimeUnit unit) throws InterruptedException { try { markAsHardwait(hardwaitingThreads, Thread.currentThread()); return embedded.await(time, unit); } finally { freeIfHardwait(hardwaitingThreads, Thread.currentThread()); } } public boolean awaitUntil(Date deadline) throws InterruptedException { try { markAsHardwait(hardwaitingThreads, Thread.currentThread()); return embedded.awaitUntil(deadline); } finally { freeIfHardwait(hardwaitingThreads, Thread.currentThread()); } } public void signal() { embedded.signal(); } public void signalAll() { embedded.signalAll(); } } // Return a condition variable that support detection of deadlocks public Condition newCondition() { return new DeadlockDetectingCondition(this, super.newCondition()); } // // Testing routines here // // These are very simple tests -- more tests will have to be written a b c 都被注册到 deadlockLocksRegistry 中 private static Lock a = new DeadlockDetectingLock(false, true); private static Lock b = new DeadlockDetectingLock(false, true); private static Lock c = new DeadlockDetectingLock(false, true); private static Condition wa = a.newCondition(); private static Condition wb = b.newCondition(); private static Condition wc = c.newCondition(); private static void delaySeconds(int seconds) { try { Thread.sleep(seconds * 1000); } catch (InterruptedException ex) { } } private static void awaitSeconds(Condition c, int seconds) { try { c.await(seconds, TimeUnit.SECONDS); } catch (InterruptedException ex) { } } private static void testOne() { new Thread(new Runnable() { public void run() { System.out.println("thread one grab a"); a.lock(); delaySeconds(2); System.out.println("thread one grab b"); b.lock(); delaySeconds(2); a.unlock(); b.unlock(); } }).start(); new Thread(new Runnable() { public void run() { System.out.println("thread two grab b"); b.lock(); delaySeconds(2); System.out.println("thread two grab a"); a.lock(); delaySeconds(2); a.unlock(); b.unlock(); } }).start(); } private static void testTwo() { new Thread(new Runnable() { public void run() { System.out.println("thread one grab a"); a.lock(); delaySeconds(2); System.out.println("thread one grab b"); b.lock(); delaySeconds(10); a.unlock(); b.unlock(); } }).start(); new Thread(new Runnable() { public void run() { System.out.println("thread two grab b"); b.lock(); delaySeconds(2); System.out.println("thread two grab c"); c.lock(); delaySeconds(10); b.unlock(); c.unlock(); } }).start(); new Thread(new Runnable() { public void run() { System.out.println("thread three grab c"); c.lock(); delaySeconds(4); System.out.println("thread three grab a"); a.lock(); delaySeconds(10); c.unlock(); a.unlock(); } }).start(); } private static void testThree() { new Thread(new Runnable() { public void run() { System.out.println("thread one grab b"); b.lock(); System.out.println("thread one grab a"); a.lock(); delaySeconds(2); System.out.println("thread one waits on b"); awaitSeconds(wb, 10); a.unlock(); b.unlock(); } }).start(); new Thread(new Runnable() { public void run() { delaySeconds(1); System.out.println("thread two grab b"); b.lock(); System.out.println("thread two grab a"); a.lock(); delaySeconds(10); b.unlock(); c.unlock(); } }).start(); } public static void main(String args[]) { int test = 1; if (args.length > 0) test = Integer.parseInt(args[0]); switch(test) { case 1: testOne(); // 2 threads deadlocking on grabbing 2 locks break; case 2: testTwo(); // 3 threads deadlocking on grabbing 2 out of 3 locks break; case 3: testThree(); // 2 threads deadlocking on 2 locks with CV wait break; default: System.err.println("usage: java DeadlockDetectingLock [ test# ]"); } delaySeconds(60); System.out.println("--- End Program ---"); System.exit(0); } }
以上代码是:java Thread 第三版 第六章的代码,详细请查看原始代码
发表评论
-
Thread.isInterrupted 的理解
2017-05-24 21:01 1797interrupt方法用于中断线程。调用该方法的线程的状态 ... -
Condition&(wait,notify)
2017-05-22 10:58 521Condition.await和Object.wait ... -
AQS-预备-背景
2017-05-20 18:16 561AbstractQueuedSynchronizer: ... -
LockSupport
2017-05-19 22:15 535LockSupport类是Java6(JSR166-JUC ... -
Synchronized&AbstractQueuedSynchronizer[摘抄]
2017-05-19 21:29 472目前在Java中存在两种锁机制:synchronized和 ... -
CountDownLatch/CyclicBarrier
2017-05-19 20:59 939CountDownLatch: 功能:是一个同步工具类 ... -
Thread-wait/notify
2017-05-19 11:59 611java 线程通过对象的Wait和Notify进行同步,但 ... -
AQS-预备-FIFOMutex
2017-05-18 20:25 482通过AtomicBoolean 和队列 ... -
AQS-预备知识 CLH lock queue[摘抄]
2017-05-18 20:07 368经典! -
多个线程到达后才能执行某个任务,并且只能执行一次
2015-04-02 23:51 3962有一种场景:多个线程到达(比如合并多个线程返回的结果)后才能执 ... -
ThreadLocal 在web环境下使用的边界问题
2014-06-12 13:30 3486ThreadLocal 相关分析,请查看http://wang ... -
原码剖析之ThreadPoolExecutor进阶
2013-06-17 17:15 1710继续ThreadPoolExecutor 线程池的分析~~~~ ... -
原码剖析之ThreadPoolExecutor入门
2013-06-15 10:44 1401jdk 1.5 开始提供支持线 ... -
源码剖析之ThreadLocal
2013-06-08 12:57 3197背景:1、如果一个对象 ... -
源码剖析之CyclicBarrier
2013-06-07 00:07 2828CyclicBarrier:jdk current 包提供了一 ... -
Thread的join方法
2013-02-25 23:44 1553Thread类中的join方法的语义: void java. ... -
lock 锁class类对象和实例对象
2013-02-25 23:18 2126java thread 线程中 的synchronized关键 ... -
异常与锁的释放(synchronized )
2013-02-16 23:28 5391synchronized 获取的锁,在方法抛出异常的时候会自动 ... -
异常与锁的释放(lock)
2013-02-16 22:57 2544获取lock锁后发生异常后,线程退出,lock锁不释放 p ...
相关推荐
Loaderlock检测在一个拥有操作系统loader lock的线程上(如上例的video的运行线程)运行托管代码的情况。这样做有可能会引起死锁,并且有可能在操作系统加载器初始化DLL前被使用。虽然这样做很有必要,但在进行开发...
基于程序在运行时不需要一开始都装入内存(局部性原理),更不应该把最近较长一段时间内不用的程序装入内存。 (2)页表的作用是将逻辑页号转换为物理块号。 (3)页面淘汰算法 先进先出算法(FIFO)...
InnoDB在它自己的锁定表中自动检测事务死锁并且回滚事务。InnoDB用LOCK TABLES语句注意到锁定设置。默认值是50秒 bulk_insert_buffer_size = 1024M # 批量插入缓存大小, 这个参数是针对MyISAM存储引擎来说的。适用...
简单来说是本身可视为电子化的文件柜——存储电子文件的处所,用户可以对文件中的数据运行新增、截取、更新、删除等操作。 常见的数据模型 1. 层次结构模型: 层次结构模型实质上是一种有根结点的定向有序树,IMS...
43 <br>0061 树的实现 44 <br>3.2 排序 48 <br>0062 如何实现选择排序算法 48 <br>0063 如何实现冒泡排序算法 49 <br>0064 如何实现快速排序算法 50 <br>0065 如何实现插入排序算法 ...
§3.2.8 当参数指定错误时怎么办? 70 §3.3 参数内容说明 70 §3.4 DBA常用参数说明 71 §3.4.1 跟踪文件路径(BACKGROUND_DUMP_DEST) 71 §3.4.2 在缓冲区驻留对象(BUFFER_POOL_KEEP) 71 §3.4.3 版本兼容...