博客
关于我
并发编程--死锁
阅读量: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/

    你可能感兴趣的文章
    mysql会对联合索性排序优化_MySQL索引优化实战
    查看>>
    MySQL作为服务端的配置过程与实际案例
    查看>>
    Mysql使用命令行备份数据
    查看>>
    MySQL保姆级教程(SQL语法基础篇)从小白到高手的进阶指南,收藏这一篇就够了
    查看>>
    MySQL修改root密码的各种方法
    查看>>
    MySQL修改root密码的多种方法
    查看>>
    mysql修改一列属性
    查看>>
    MySQL修改密码报错ERROR 1396 (HY000): Operation ALTER USER failed for ‘root‘@‘localhost‘
    查看>>
    Mysql全局优化参数
    查看>>
    MySQL全文索引实现简单版搜索引擎
    查看>>
    MySQL全面瓦解:安装部署与准备
    查看>>
    mysql共享锁与排他锁
    查看>>
    MySQL内存表使用技巧
    查看>>
    MySQL再叙(体系结构、存储引擎、索引、SQL执行过程)
    查看>>
    mysql出现错误的解决办法
    查看>>
    MySQL函数
    查看>>
    mysql函数汇总之字符串函数
    查看>>
    mysql函数汇总之数学函数
    查看>>
    mysql函数汇总之日期和时间函数
    查看>>
    mysql函数汇总之条件判断函数
    查看>>