博客
关于我
并发编程--死锁
阅读量:608 次
发布时间:2019-03-12

本文共 2017 字,大约阅读时间需要 6 分钟。

什么是多线程死锁?

多线程以及多进程改善了系统资源的利用率并提高了系统的处理能力。然而,并发执行也带来了新的问题——死锁。死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些线程都将无法向前推进。

死锁主要由两个因素引起:系统资源的竞争和进程推进顺序的不合理。

系统资源的竞争是导致死锁的主要原因之一。许多现代系统都依赖有限的不可剥夺资源(如CPU时间片、磁盘I/O等)来提供服务。这些资源无法同时满足多个进程的需求。如果各进程试图在同一时间请求同一资源,就可能导致死锁。此外,线程间直接调用同步块(如synchronized关键字)也可能引发死锁。

进程推进顺序不合理是另一个导致死锁的主要原因。在并发环境下,进程通常交替地发起和释放资源请求。假设两个进程P1和P2分别持有资源R1和R2,而P1试图请求R2,P2试图请求R1,就有可能出现僵局,导致两者无法继续执行。

以下代码示例展示了一种可能导致死锁的情形:

package com.yxl.demo.ThreadTest;public class Test5 {    public static void main(String[] args) throws InterruptedException {        TestDemo thread = new TestDemo();        Thread t1 = new Thread(thread, "窗口一");        Thread t2 = new Thread(thread, "窗口二");        t1.start();        Thread.sleep(40);        thread.flag = false;        t2.start();    }}class TestDemo implements Runnable {    private volatile int count = 100;    private Object object = new Object();    boolean flag = true;    @Override    public void run() {        if (flag) {            while (count > 0) {                synchronized (object) {                    sale();                }            }        } else {            while (count > 0) {                sale();            }        }    }    public synchronized void sale() {        try {            Thread.sleep(50);        } catch (Exception e) {        }        synchronized (object) {            if (count > 0) {                System.out.println(Thread.currentThread().getName() + "出售:" + (100 - count + 1));                count--;            }        }    }}

在默认情况下,这段代码会导致死锁。运行结果显示,主线程无法正常退出,加锁操作持续存在,导致程序卡顿。

在这个案例中,两个线程都试图在同一锁object上同步操作。线程t1首先获取锁并执行sale(),t2在t1启动后的40ms后启动,并试图获取同一个锁。由于t1仍在占用锁,t2只能等待。此时,若t1释放了锁,t2可能继续执行。然而,原代码的其他逻辑(如flag的设置)导致资源长时间占用,导致死锁发生。

如何解决死锁问题?

解决死锁问题可以采取以下措施:

  • 加锁顺序(Lock Ordering):确保线程在对多个锁加锁时,按照特定顺序操作,避免竞争。

  • 加锁时限(锁定超时):在尝试获取锁时设置超时,超过时间限制后放弃锁请求并释放已经占有的锁。这有助于减少死锁发生的概率。

  • 防止死锁检测(Deadlock Detection):采用他urka检测机制,监测是否存在长时间占锁状态,以便及时处理。现代一些的环境中,这种方法变得越来越常见。

  • 此外,针对上述代码,可以通过调整运行逻辑来避免死锁问题。例如,允许线程在获取锁前先检查资源是否可用。这样可以避免多线程在同一个锁上进行长时间等待,减少死锁风险。

    转载地址:http://dwwaz.baihongyu.com/

    你可能感兴趣的文章
    mysql5.7 for windows_MySQL 5.7 for Windows 解压缩版配置安装
    查看>>
    Webpack 基本环境搭建
    查看>>
    mysql5.7 安装版 表不能输入汉字解决方案
    查看>>
    MySQL5.7.18主从复制搭建(一主一从)
    查看>>
    MySQL5.7.19-win64安装启动
    查看>>
    mysql5.7.19安装图解_mysql5.7.19 winx64解压缩版安装配置教程
    查看>>
    MySQL5.7.37windows解压版的安装使用
    查看>>
    mysql5.7免费下载地址
    查看>>
    mysql5.7命令总结
    查看>>
    mysql5.7安装
    查看>>
    mysql5.7性能调优my.ini
    查看>>
    MySQL5.7新增Performance Schema表
    查看>>
    Mysql5.7深入学习 1.MySQL 5.7 中的新增功能
    查看>>
    Webpack 之 basic chunk graph
    查看>>
    Mysql5.7版本单机版my.cnf配置文件
    查看>>
    mysql5.7的安装和Navicat的安装
    查看>>
    mysql5.7示例数据库_Linux MySQL5.7多实例数据库配置
    查看>>
    Mysql8 数据库安装及主从配置 | Spring Cloud 2
    查看>>
    mysql8 配置文件配置group 问题 sql语句group不能使用报错解决 mysql8.X版本的my.cnf配置文件 my.cnf文件 能够使用的my.cnf配置文件
    查看>>
    MySQL8.0.29启动报错Different lower_case_table_names settings for server (‘0‘) and data dictionary (‘1‘)
    查看>>