【多线程】-- 11 死锁、Lock锁

news2024/11/19 10:19:12

多线程

7 死锁

  • 多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行,而导致两个或多个线程都在等待对方释放资源,都停止执行的情形。某一个同步块同时拥有”两个以上对象的锁“时,就可能会发生死锁的问题。
package com.duo.deadlock;

//死锁:多个线程互相抱着对方需要的资源,然后形成僵持
public class DeadLock {

    public static void main(String[] args) {
        MakeUp hua = new MakeUp(0, "Hua");
        MakeUp hong = new MakeUp(1, "Hong");

        hua.start();
        hong.start();
    }
}

class LipStick {
}

class Mirror {
}

class MakeUp extends Thread {

    static final LipStick lipStick = new LipStick();
    static final Mirror mirror = new Mirror();

    int choice;
    String girlName;

    public MakeUp(int choice, String girlName) {
        this.choice = choice;
        this.girlName = girlName;
    }

    @Override
    public void run() {
        try {
            makeup();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void makeup() throws InterruptedException {
        if (choice == 0) {
            synchronized (lipStick) {
                System.out.println(this.girlName + "获得口红的锁");
                Thread.sleep(1000);
                synchronized (mirror) {
                    System.out.println(this.girlName + "获得镜子的锁");
                }
            }
            
        } else {
            synchronized (mirror) {
                System.out.println(this.girlName + "获得镜子的锁");
                Thread.sleep(2000);
                synchronized (lipStick) {
                    System.out.println(this.girlName + "获得口红的锁");
                }
            }
            
        }
    }
}

运行结果:

图1

此时发现,运行窗口会卡顿且不会自动停止,正是由于上述代码makeup() {}中出现了死锁现象。

倘若对代码进行如下改动:

private void makeup() throws InterruptedException {
    if (choice == 0) {
        synchronized (lipStick) {
            System.out.println(this.girlName + "获得口红的锁");
            Thread.sleep(1000);
        }
        synchronized (mirror) {
            System.out.println(this.girlName + "获得镜子的锁");
        }

    } else {
        synchronized (mirror) {
            System.out.println(this.girlName + "获得镜子的锁");
            Thread.sleep(2000);
        }
        synchronized (lipStick) {
            System.out.println(this.girlName + "获得口红的锁");
        }
    }
}

运行结果:

图2

可以看到,将makeup() {}中的synchronized {}块并列排放,死锁消除,程序正常运行停止。

  • 死锁避免方法
    • 产生死锁的四个必要条件:
      1. 互斥条件:一个资源每次只能被一个进程使用
      2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
      3. 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺
      4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
    • 上述四个必要条件中,只要想办法突破其中任意一个或多个条件,就可以避免死锁发生。

8 Lock(锁)

  • 从JDK5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。同步锁使用Lock对象充当
  • java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象
  • ReentrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁

未加Lock锁之前:

package com.duo.deadlock;

//测试Lock锁
public class LockTest {

    public static void main(String[] args) {
        LockTest1 lockTest1 = new LockTest1();

        new Thread(lockTest1).start();
        new Thread(lockTest1).start();
        new Thread(lockTest1).start();
    }
}

class LockTest1 implements Runnable {

    int ticketNum = 10;

    @Override
    public void run() {
        while (true) {
            if (ticketNum > 0) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(ticketNum--);
            } else {
                break;
            }
        }
    }
}

运行结果:

图3

可以看到,此时的线程是不安全的。

加入Lock锁之后:

package com.duo.deadlock;

import java.util.concurrent.locks.ReentrantLock;

//测试Lock锁
public class LockTest {

    public static void main(String[] args) {
        LockTest1 lockTest1 = new LockTest1();

        new Thread(lockTest1).start();
        new Thread(lockTest1).start();
        new Thread(lockTest1).start();
    }
}

class LockTest1 implements Runnable {

    int ticketNum = 10;

    //定义lock锁
    private final ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            try {
                lock.lock();  //加锁
                if (ticketNum > 0) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(ticketNum--);
                } else {
                    break;
                }
            }finally {
                lock.unlock();  //解锁
            }
        }
    }
}

运行结果:

图4

注意到此时的结果实际上是挨个”排队“输出的。

synchronized与Lock的对比

  • Lock是显式锁(手动开启和关闭锁,不要忘记关闭锁),而synchronized是隐式锁,出了作用域自动释放

  • Lock只有代码块锁,synchronized有代码块和方法锁

  • 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好,并且具有更好的扩展性(可提供更多的子类)

  • 优先使用顺序:

    • Lock > 同步代码块(已经进入了方法体,分配了相应资源) > 同步方法(在方法体之外)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1283047.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nn.AdaptiveAvgPool2d(output_size)输入和输出怎么回事?

前言 nn.AdaptiveAvgPool2d(output_size) 函数作用:自适应进行平均池化。不用管输入、stride、padding,函数参数只有输出大小,其他的这个函数帮你搞定。 问题就是,我想知道他是咋搞定的? 1 函数的使用 先把例子摆上…

Socket和Http的通讯原理,遇到攻击会受到哪些影响以及如何解决攻击问题。

德迅云安全-领先云安全服务与解决方案提供商 Socket和HTTP通信原理: Socket通信原理: Socket是一种应用程序编程接口(API),用于在单个进程或多个进程之间进行通信。它提供了一种灵活的、异步的通信方式,使…

【蓝桥杯】翻硬币

翻硬币 思路&#xff1a; 其实有点贪心的意思&#xff0c;依次比较&#xff0c;不同就1&#xff0c;然后修改自己的字符串和下一个的字符串&#xff0c;再匹配。 #include<iostream> #include<string> using namespace std;string now,res;int main(void) {cin&g…

安美数字酒店宽带运营系统 SQL注入漏洞复现

0x01 产品简介 HiBOS酒店宽带运营系统隶属于安美世纪(北京)科技有限公司开发的一套酒店宽带管理系统。 0x02 漏洞概述 安美数字酒店宽带运营系统 online_status.php、language.php等接口处存在SQL注入漏洞,未经身份认证的攻击者可以通过此漏洞获取数据库权限,进一步利用可…

算法通关村第十三关-黄金挑战数论问题

计数质数 描述 : 给定整数 n &#xff0c;返回 所有小于非负整数 n 的质数的数量 。 题目 : LeetCode 204.计数质数 : 204. 计数质数 分析 : 解决这个题有一个有效的方法&#xff0c;叫埃氏筛 , 后来又产生了线性筛&#xff0c;奇数筛等改进的方法。 基本思想是如果 x是…

【ElementUI】一行代码解决图片预览

【ElementUI】一行代码解决图片预览 只需要在图片标签上加入:preview-src-list 只需要在图片标签上加入:preview-src-list 完整代码如下&#xff1a; <el-table-column label"封面" align"center" prop"cover" :sort-orders"[descend…

赴日程序员高年薪过上“躺平”生活?

日本的IT行业想要达到的高薪&#xff0c;也是需要很多资历和经验的&#xff0c;不过即使你是新卒&#xff0c;也能拿到相比国内来说让你满意的薪资。 刚入职的起薪是20-23万日元/月&#xff0c;情报信息业出身&#xff0c;技术掌握不错&#xff0c;起薪是25万-30万日元。之后经…

vue项目配置多个代理

在本地.env文件配置本地/测试/预发/正式 路径&#xff1a; 在vue.config.js 里面配置&#xff1a; module.exports defineConfig({transpileDependencies: false,lintOnSave: false,outputDir: process.env.VUE_APP_DIST,publicPath: /,css: {loaderOptions: {postcss: {// p…

生命在于折腾——将心脏献给计算机

还记得当初自己为什么选择计算机&#xff1f; 看到这个话题的时候&#xff0c;我害羞了&#xff0c;是的&#xff0c;你没有看错&#xff0c;我害羞了&#xff0c;这并不是说我有恋物癖&#xff0c;只是我对经过我手中的计算机&#xff0c;都有一种独特的情感。 背景 我是一…

蓝桥杯-03-蓝桥杯学习计划

蓝桥杯-03-蓝桥杯学习计划 参考资料 相关文献 报了蓝桥杯比赛&#xff0c;几乎零基础&#xff0c;如何准备&#xff0c;请大牛指导一下。谢谢&#xff1f; 蓝桥杯2022各组真题汇总(完整可评测) 基础学习 C语言网 ACM竞赛入门,蓝桥杯竞赛指南 廖雪峰的官方官网 算法题单 洛谷…

【Linux20.04-qt5.12.4软件安装与初步使用-qt在Linux使用-记录-笔记】

【Linux-qt软件安装与初步使用-qt在Linux使用-记录-笔记】 1、概述2、环境说明3、步骤总结1、了解并选择自己想要安装的版本2、访问 Qt 官方网站3、在 Qt 网站上找到下载部分&#xff08;自己想下载&#xff09;4、下载完成后&#xff0c;给安装程序文件赋予执行权限。5、自动配…

Python解释器的安装【侯小啾python基础领航计划 系列(一)】

Python解释器的安装【侯小啾python基础领航计划 系列(一)】 大家好,我是博主侯小啾, 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ…

人工智能与供应链行业融合:开启智能化供应链的新时代

随着人工智能技术的快速发展&#xff0c;供应链行业正迎来革命性变革。本文将探索人工智能在供应链管理中的应用领域&#xff0c;并分析其带来的益处和挑战&#xff0c;展望人工智能与供应链融合的未来发展趋势。 引言 供应链管理是企业运营中不可或缺的重要组成部分。它涵盖了…

你对SPA单页面的理解,它的优缺点分别是什么?

面试官&#xff1a;你对SPA单页面的理解&#xff0c;它的优缺点分别是什么&#xff1f;如何实现SPA应用呢 一、什么是SPA SPA&#xff08;single-page application&#xff09;&#xff0c;翻译过来就是单页应用SPA是一种网络应用程序或网站的模型&#xff0c;它通过动态重写当…

Grid++Report关于一张纸打多页

1.如果是纵向分割&#xff0c;设置【页分割数】打印即可 2.如果是多页排版&#xff0c;可在打印时选择版数 也可以设置打印前脚本事件: Report.Printer.SheetPages 2;//版数 Report.Printer.SheetPaperSize 9;//A4纸code

Gorm框架入门

文章目录 安装连接数据库Gorm基本示例自动迁移创建数据行查询数据更新数据删除数据 Gorm Model主键表名列名 时间戳CreatedAtUpdatedAtDeletedAt GORM&#xff08;Go Object Relational Mapper&#xff09;是一个在Go语言中使用的对象关系映射&#xff08;ORM&#xff09;库。它…

网工学习10-IP地址

一、IP地址概念 IP地址是一个32位的二进制数&#xff0c;它由网络ID和主机ID两部份组成&#xff0c;用来在网络中唯一的标识的一台计算机。网络ID用来标识计算机所处的网段&#xff1b;主机ID用来标识计算机在网段中的位置。IP地址通常用4组3位十进制数表示&#xff0c;中间用…

lua完整学习笔记

lua注释 &#xff0d;&#xff0d; 单行注释 &#xff0d;&#xff0d;[[ 多行注释 ]]-- lua数据结构 nil 无效值与Java的Null类似&#xff0c;但是在条件表示中是false boolean 布尔值&#xff0c;ture或者false number 双精度类型的浮点数 string 字…

撬动内容 10 倍增长,如何实现企业级全域内容治理

随着流量利好即将出尽&#xff0c;那些曾经仅依靠流量堆砌的营销策略&#xff0c;如今显得黯然失色。在新的市场环境下&#xff0c;更大的增长机会在哪里&#xff1f; 继续追求「运营效率」还是确立全新「战略定位」&#xff0c;企业的增长还有哪些新的可能性&#xff1f; 在刚…

日常操作之新增物料组并自动关联科目

1、创建物料组 OMSF 后台配置路径如下图&#xff1a; 直接创建一个物料组&#xff0c;给到对应描述即可。这里没有控制参数 2.、创建评估类 OMSK 我们在OBYC中配置科目时&#xff0c;是没有通过物料组的维度配置对应科目哦&#xff0c;但是评估类经常会用到GBB中的科目配置都…