zoukankan      html  css  js  c++  java
  • Java 死锁

    Java的线程锁是可重入的锁。

    什么是可重入的锁?我们还是来看例子:

    public class Counter {
        private int count = 0;
    
        public synchronized void add(int n) {
            if (n < 0) {
                dec(-n);
            } else {
                count += n;
            }
        }
    
        public synchronized void dec(int n) {
            count += n;
        }
    }
    View Code

    观察synchronized修饰的add()方法,一旦线程执行到add()方法内部,说明它已经获取了当前实例的this锁。如果传入的n < 0,将在add()方法内部调用dec()方法。由于dec()方法也需要获取this锁,现在问题来了:

    对同一个线程,能否在获取到锁以后继续获取同一个锁?

    答案是肯定的。JVM允许同一个线程重复获取同一个锁,这种能被同一个线程反复获取的锁,就叫做可重入锁。

    由于Java的线程锁是可重入锁,所以,获取锁的时候,不但要判断是否是第一次获取,还要记录这是第几次获取。每获取一次锁,记录+1,每退出synchronized块,记录-1,减到0的时候,才会真正释放锁。

    死锁

    一个线程可以获取一个锁后,再继续获取另一个锁。例如:

    public void add(int m) {
        synchronized(lockA) { // 获得lockA的锁
            this.value += m;
            synchronized(lockB) { // 获得lockB的锁
                this.another += m;
            } // 释放lockB的锁
        } // 释放lockA的锁
    }
    
    public void dec(int m) {
        synchronized(lockB) { // 获得lockB的锁
            this.another -= m;
            synchronized(lockA) { // 获得lockA的锁
                this.value -= m;
            } // 释放lockA的锁
        } // 释放lockB的锁
    }
    View Code

    在获取多个锁的时候,不同线程获取多个不同对象的锁可能导致死锁。对于上述代码,线程1和线程2如果分别执行add()dec()方法时:

    • 线程1:进入add(),获得lockA
    • 线程2:进入dec(),获得lockB

    随后:

    • 线程1:准备获得lockB,失败,等待中;
    • 线程2:准备获得lockA,失败,等待中。

    此时,两个线程各自持有不同的锁,然后各自试图获取对方手里的锁,造成了双方无限等待下去,这就是死锁。

    死锁发生后,没有任何机制能解除死锁,只能强制结束JVM进程。

    因此,在编写多线程应用时,要特别注意防止死锁。因为死锁一旦形成,就只能强制结束进程。

    那么我们应该如何避免死锁呢?答案是:线程获取锁的顺序要一致。即严格按照先获取lockA,再获取lockB的顺序,改写dec()方法如下:

    public void dec(int m) {
        synchronized(lockA) { // 获得lockA的锁
            this.value -= m;
            synchronized(lockB) { // 获得lockB的锁
                this.another -= m;
            } // 释放lockB的锁
        } // 释放lockA的锁
    }
    View Code

    参考资料

    廖雪峰Java

  • 相关阅读:
    JQueryMobile开发必须的知道的知识
    15款很棒的 JavaScript 开发工具
    浅谈 JavaScript 编程语言的编码规范
    也谈谈js的压缩,jquery压缩。【转】
    jQuery实现点击单选按钮切换选中状态效果
    JavaScript入门学习书籍的阶段选择
    试读《基于MVC的JavaScript Web富应用开发》— 不一样的JavaScript
    javaScript之function定义
    利用Powershell自动部署asp.net mvc网站项目 (一)
    【好文收藏】javascript中event对象详解
  • 原文地址:https://www.cnblogs.com/xumaomao/p/12843276.html
Copyright © 2011-2022 走看看