- 浏览: 342187 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (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 1864interrupt方法用于中断线程。调用该方法的线程的状态 ... -
Condition&(wait,notify)
2017-05-22 10:58 567Condition.await和Object.wait ... -
AQS-预备-背景
2017-05-20 18:16 613AbstractQueuedSynchronizer: ... -
LockSupport
2017-05-19 22:15 594LockSupport类是Java6(JSR166-JUC ... -
Synchronized&AbstractQueuedSynchronizer[摘抄]
2017-05-19 21:29 517目前在Java中存在两种锁机制:synchronized和 ... -
CountDownLatch/CyclicBarrier
2017-05-19 20:59 980CountDownLatch: 功能:是一个同步工具类 ... -
Thread-wait/notify
2017-05-19 11:59 663java 线程通过对象的Wait和Notify进行同步,但 ... -
AQS-预备-FIFOMutex
2017-05-18 20:25 523通过AtomicBoolean 和队列 ... -
AQS-预备知识 CLH lock queue[摘抄]
2017-05-18 20:07 440经典! -
多个线程到达后才能执行某个任务,并且只能执行一次
2015-04-02 23:51 4018有一种场景:多个线程到达(比如合并多个线程返回的结果)后才能执 ... -
ThreadLocal 在web环境下使用的边界问题
2014-06-12 13:30 3528ThreadLocal 相关分析,请查看http://wang ... -
原码剖析之ThreadPoolExecutor进阶
2013-06-17 17:15 1760继续ThreadPoolExecutor 线程池的分析~~~~ ... -
原码剖析之ThreadPoolExecutor入门
2013-06-15 10:44 1440jdk 1.5 开始提供支持线 ... -
源码剖析之ThreadLocal
2013-06-08 12:57 3249背景:1、如果一个对象 ... -
源码剖析之CyclicBarrier
2013-06-07 00:07 2894CyclicBarrier:jdk current 包提供了一 ... -
Thread的join方法
2013-02-25 23:44 1616Thread类中的join方法的语义: void java. ... -
lock 锁class类对象和实例对象
2013-02-25 23:18 2212java thread 线程中 的synchronized关键 ... -
异常与锁的释放(synchronized )
2013-02-16 23:28 5447synchronized 获取的锁,在方法抛出异常的时候会自动 ... -
异常与锁的释放(lock)
2013-02-16 22:57 2604获取lock锁后发生异常后,线程退出,lock锁不释放 p ...
相关推荐
### SQL Server 死锁检测详解 #### 死锁的基本概念 死锁是计算机科学领域一个重要的概念,尤其在数据库管理系统中极为关键。死锁的本质是一种僵持状态,它发生在两个或多个事务相互等待对方释放资源时,从而导致...
### Linux内核死锁检测——Lockdep详解 #### 一、Lockdep简介 **Lockdep** 是 Linux 内核提供的一项重要功能,用于协助开发者发现并解决死锁问题。死锁通常指的是两个或多个进程(在 Linux 内核中通常指的是任务)...
- 使用系统视图:许多数据库系统提供了内置视图(如SQL Server的sys.dm_tran_locks,Oracle的v$lock),用于查看当前的锁定状态,帮助找出潜在的死锁。 - 错误日志:数据库系统通常会在发生死锁时记录错误信息,通过...
Oracle数据库内置了死锁检测机制,当检测到死锁时,会自动选择一个受害者事务进行回滚,释放资源,从而打破死锁。另外,DBA可以通过以下方式手动检查: - 使用`v$session_wait`视图查找等待类型的`ENQ: TX - row ...
而"死锁监控方案.txt"可能包含了一种具体的死锁检测和处理的实现方法,如定时检测系统状态,一旦发现死锁迹象,就采取相应的恢复措施。 总结来说,解决多线程死锁问题需要从预防、避免、检测和恢复四个方面进行考虑...
4. **死锁检测与恢复**:SQLite内建了死锁检测机制,当检测到死锁时,会回滚其中一个事务以解除死锁。但也可以在应用程序层面主动检测和处理死锁。 5. **使用WAL模式**:Write-Ahead Logging(预写日志)模式能有效...
SQL Server提供了多种工具和方法来检测和分析死锁,以便管理员能够及时发现并解决问题。本文将详细介绍如何在SQL Server中分析死锁进程,特别是如何通过存储过程来捕捉和分析死锁信息。 ### 死锁分析存储过程 在...
为了解决这个问题,SQL Server引入了死锁检测机制,并会在发现死锁时选择一个事务进行回滚,以打破僵局,这个过程称为死锁牺牲品。 SQL Server Profiler是SQL Server的一个重要工具,用于跟踪和记录服务器活动,...
除了JCarder,Java还提供了其他的死锁检测工具和手段,如JConsole、VisualVM和JDK自带的jstack命令。这些工具都可以帮助我们分析线程状态,找出可能导致死锁的原因。 在编写多线程程序时,预防死锁的一些最佳实践...
通过使用如“sp_who_lock”这样的存储过程,数据库管理员可以获得系统状态的实时洞察,及时发现并解决阻塞和死锁问题,从而确保数据库系统的高效稳定运行。同时,合理设计事务逻辑,优化查询和索引,也是防止阻塞和...
- **超时机制**:SQL Server默认设置了一个超时时间,当事务等待超过这个时间仍未获得资源,就会触发死锁检测。系统会选择一个事务作为死锁的受害者,并中止该事务。 - **死锁监控**:通过创建警报或者触发器来...
- 死锁检测:InnoDB有内置的死锁检测机制,会在事务等待一段时间(可通过`innodb_lock_wait_timeout`参数设置)后进行检查。 - 死锁解决:一旦检测到死锁,InnoDB会选择一个事务作为牺牲品,回滚该事务的操作,以...
标题所提及的"查看数据库死锁信息"是一个至关重要的任务,因为死锁可能导致数据库性能下降,甚至影响到服务的正常运行。当出现"Deadlock found when trying to get to lock; try restarting transaction"这样的错误...
### 死锁检测与分析 #### 使用跟踪标志1204 在SQL Server中,启用跟踪标志1204是检测死锁的一个有效方式。当启用此标志后,SQL Server会在发生死锁时生成详细的死锁信息报告,包括涉及的事务、锁定的资源以及死锁...
2. 使用死锁检测机制,当检测到死锁时,MySQL会回滚其中一个事务以打破死锁循环。 3. 优化SQL查询,避免全表扫描,减少间隙锁的使用。 4. 考虑使用更宽松的事务隔离级别,如可重复读(Repeatable Read)降级为读已...
3. **使用死锁检测和自动解决机制**:Oracle提供了死锁检测功能,一旦检测到死锁,系统会自动选择牺牲其中一个事务,解决死锁。 4. **优化SQL语句**:合理使用SQL提示(如`/*+ NO_MERGE */`),减少不必要的全表扫描...
#### 二、死锁检测与处理 本节将详细介绍如何检测 SQL Server 中的死锁,并提供一种实用的解决方案来处理这些死锁问题。 ##### 1. 检测死锁 在 SQL Server 中,可以通过多种方式检测到死锁的发生: - **SQL ...
#### 三、MySQL死锁检测 MySQL通过内部机制自动检测死锁。当检测到死锁时,通常会选择回滚其中一个事务来解除死锁。可以通过查询`INFORMATION_SCHEMA.INNODB_TRX`表来查看当前活跃的事务信息,包括事务的状态、开始...