【JavaEE】【多线程】synchronized和死锁

news2024/11/25 18:37:22

目录

  • 一、synchronized详解
    • 1.1 互斥
    • 1.2 可重入
  • 二、死锁
    • 2.1 死锁成因
    • 2.2 避免死锁

一、synchronized详解

1.1 互斥

synchronized 会起到互斥效果, 某个线程执行到某个对象的 synchronized 中时, 其他线程如果也执行到
同一个对象 synchronized 就会阻塞等待.

语法:

synchronized(变量){
//修改操作
}

()括号内的变量不重要,作用是区分加锁对象是否一样,如果对同一个对象加锁,那么两个操作就会产生“blocked”锁竞争阻塞问题,后一个线程就会等到前一个线程解锁再执行。
进入左大括号 ‘{’ 就是加锁,出了右大括号 ‘}’ 就是解锁。

写一个例子,就会出现预期结果10000:

public class Demo7 {
    private static int ret;
    public static void main(String[] args) throws InterruptedException {
        Object block = new Object();
        
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {                
                synchronized (block){
                    ret++;
                }
                
            }
        });
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                synchronized (block){
                    ret++;
                }

            }
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(ret);;
    }
}

synchronized还可以修饰方法(静态方法也行)。

  • synchronized修饰实例方法:
class Counter{
    public int ret;
    public void increase1() {
        synchronized (this) {
            ret++;
        }
    }
    //简化版本
    synchronized public void increase2() {
        ret++;
    }
}
  • synchronized修饰静态方法:相当于修饰这个类
class Counter{
	private static int ret2;
	public static void increase3() {
        synchronized (Counter.class) {
            ret2++;
        }
    }
    //简化版本
    synchronized public static void increase4() {
        ret2++;
    }
}

1.2 可重入

可重入就是指一个线程连续针对一个对象加多次锁,不会出现“死锁”现象称为可重入。

死锁:自己把自己锁死。
举个例子,假如synchronized不是可重入锁:

synchronized (block) {
	synchronized(block) {
	//代码
	} //右大括号}2
}  //右大括号}1

在进入第一个synchronized的时候,加上一把锁,此时已经是“锁定状态”,
当我们进入到第二个synchronized的时候要加锁,就发生“阻塞等待”,就要等到第一个锁走到右大括号}1解完锁才能加,
然而第一个锁走到右大括号}1解锁,又需要第二把锁创建走完到右大括号}2。
这是线程就卡死了,这就是死锁。

synchronized 同步块对同一条线程来说是可重入的,不会出现自己把自己锁死的问题;

  • 可重入机制会在第一次加锁的时候记录是那个线程加的锁,然后下一次加锁如果是这个被记录线程,就直接加锁成功。这就是可重入锁的 "线程持有者"信息。
  • 可重入锁还会有一个“计数器”信息,加一把锁就加一,解一把锁就减一,当计数器递减为 0 的时候, 才真正释放锁。

二、死锁

  • 前面所说,一个线程两把锁,如果不是可重入锁就死锁了;
  • 还有两个线程两把锁,是不是可重入锁都要死锁。两个线程T1、T2,两把锁A、B;T1获取锁A,T2获取锁B,T2尝试获取锁B,T2尝试获取锁A。就如“车钥匙锁房间里了,房间钥匙锁车里了”。
public class Demo9 {
    public static void main(String[] args) {
        Object block1 = new Object();
        Object block2 = new Object();
        Thread thread1 = new Thread(()->{
            synchronized (block1) {
                System.out.println("thread1加block1");
                synchronized (block2) {
                    System.out.println("thread1加block2");
                }
            }
        });
        Thread thread2 = new Thread(()->{

            synchronized (block2) {
                System.out.println("thread2加block2");

                synchronized (block1) {
                    System.out.println("thread2加block1");
                }
            }
        });
        thread1.start();
        thread2.start();
    }
}

  • N个线程,M把锁(相当于两个线程两把锁的进阶版本):经典模型哲学家就餐问题

5个哲学家,5只筷子,哲学家坐在圆桌边,桌上放有面条,每只筷子放在每个哲学家的中间。

  1. 每个哲学家,会做两件事:
    1.1.思考人生.放下筷子,啥都不干
    1.2 吃面条.拿起左右两侧的两根筷子,开始吃面条,
  2. 哲学家啥时候吃面条,啥时候思考人生,是随机的
  3. 哲学家吃面条啥时候吃完,也是随机的,
  4. 哲学家正在吃面条的过程中,会持有左右两侧的筷子。此时相邻的哲学家如果也想吃面条,就需要阻塞等待,

当出现极端情况,每个哲学家都想吃面条,都拿起自己左手边的筷子,并且不会在没吃到面条情况下放下筷子,这时就是死锁了。

2.1 死锁成因

四个必要条件:

  1. 互斥使用(锁的基本特性):当一个线程拿到一把锁后,另一个线程要拿到这把锁就要阻塞等待;
  2. 不可抢占(锁的基本特性):当一把锁被线程拿到后,其他线程不能抢占,只能等线程自己释放锁;
  3. 请求保持(代码结构):当一个线程拿到一把锁后,再去拿其它锁的时候,已经被拿到的锁不会被释放;
  4. 循环/环路 等待(代码结构):阻塞等待的依赖关系形成环了。

2.2 避免死锁

只要上诉四个条件不成立一个就可以。
条件1,2是锁自带的特性,不能改变。

  • 对于条件3,改变代码结构,避免锁嵌套逻辑;
  • 对于条件4,可以约定加锁顺序,便面等待依赖关系成环。
    如上面的哲学家就餐问题,给每个筷子从1-5顺序编号,规定每次拿筷子只能先拿小号筷子。
  • 银行家算法,但是这种算法过于麻烦一般不用。

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

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

相关文章

AI时代程序员何去何从?提升自我还是被淘汰出局!

AI 在编程界的使用变得越来越普遍了。随着 ChatGPT 的横空出世&#xff0c;各种大语言模型如雨后春笋不断出现。国外如谷歌 Bard、Anthropic 的 Claude&#xff0c;国内如百度文心一言、阿里通义千问、讯飞星火认知大模型、昆仑万维天工大模型等。 想想看&#xff0c;以前得花好…

支持国密算法的数字证书-国密SSL证书详解

在互联网中&#xff0c;数字证书作为标志通讯各方身份信息的数字认证而存在&#xff0c;常见的数字证书大都采用国际算法&#xff0c;比如RSA算法、ECC算法、SHA2算法等。随着我国加强网络安全技术自主可控的大趋势&#xff0c;也出现了支持国密算法的数字证书-国密SSL证书。那…

【网络安全】缓存欺骗问题之查看个人资料接口

未经许可,不得转载。 文章目录 正文正文 目标网站 target.com,查看个人资料页面时,API 端点为/get_user,完整的 URL 是 https://target.com/web-api/v1/get_user?timestamp=123456(其中 timestamp 是一个易受攻击的参数)。 我注意到响应中有一个 cf-cache-status= MISS…

k8s部署Kafka集群超详细讲解

准备部署环境 Kubernetes集群信息 NAMEVERSIONk8s-masterv1.29.2k8s-node01v1.29.2k8s-node02v1.29.2 Kafka&#xff1a;3.7.1版本&#xff0c;apche版本 Zookeeper&#xff1a;3.6.3版本 准备StorageClass # kubectl get sc NAME PROVISIONER RECLA…

Docker安装ActiveMQ镜像以及通过Java生产消费activemq示例

拉取镜像 docker pull docker.io/webcenter/activemq 启动容器 docker run -d --name myactivemq -p 61616:61616 -p 8162:8161 docker.io/webcenter/activemq:latest 这样就代表启动成功了 浏览器访问 http://localhost:8162/ admin admin 开启验证 修改配置文件/opt/ac…

关于k8s集群高可用性的探究

1. k8s的高可用的核心是什么&#xff1f; 说到核心、本质 意味着要从物理层来考虑技术 k8s是一个容器编排管理工具&#xff0c;k8s受欢迎的时机 是docker容器受欢迎时&#xff0c;因为太多的docker容器&#xff0c;管理起来是一个大工程 那么刚好k8s是google自己用了十来年…

STM32L031F6P6基于CubeMX的串口通信调试笔记

用CubeMX创建项目 本实例用的PA14、PA13两个引脚&#xff0c;LPUART1。 对串口参数进行设置&#xff1a; 开启串口中断&#xff1a; 时钟源设置成内部高频时钟&#xff1a; 对项目进行设置&#xff1a; 生成代码&#xff1a; 在串口初始化函数中加入 __HAL_UART_ENA…

Asp.net Core MVC 动态路由

动态路由 asp.net core 3.0 就支持了 // 映射关系public class TranslationDatabase{private static Dictionary<string, Dictionary<string, string>> Translations new Dictionary<string, Dictionary<string, string>>{{"en", new Dictio…

《Vue3 踩坑》expose 和 defineExpose 暴露属性或方法注意事项

选项式写法 使用 选项式API - 状态选项 - expose 一定要注意&#xff1a; 接下来&#xff0c;进一步看示例说明&#xff1a; 设置 expose 仅显示列出的属性/方法才能被父组件调用&#xff1b;代码第 2 行&#xff0c;父组件可访问属性 a 和 方法 myFunc01&#xff0c;不可访…

Windows server 2022 数据中心版本的安装

安装前的准备工作&#xff1a; 1.准备好VMware虚拟机&#xff08;略&#xff09; 2.准备好镜像 图1-1 准备安装镜像 3.准备好安装的位置&#xff08;F盘2022vm文件夹&#xff09; 图1-2 选择并设定安装位置 4.开始安装 图1-3 开心VMware安装向导 图1-4 插入光盘镜像 图1-5…

视频转文字工具搜集

视频转文字工具是一种能够将视频中的音频内容转化为文字的软件或在线服务。这类工具通常支持多种视频格式和语言&#xff0c;适用于不同的场景和需求。以下是一些推荐的视频转文字工具及其特点&#xff1a; 媒关系&#xff1a;这是一款免费的视频转文字工具&#xff0c;支持多种…

ABAQUS应用11——支座弹簧

文章目录 0、背景1、ABAQUS中几类弹簧的简介2、SPRING1的性质初探 0、背景 1、ABAQUS中几类弹簧的简介 先说参考来源&#xff0c;ABAQUS2016的帮助文档里第4卷&#xff0c;32.1.1节&#xff0c;有三种弹簧&#xff08;SPRING1 、SPRING2 以及SPRINGA&#xff09;。 三种弹簧里…

【AIGC】ChatGPT提示词Prompt高效编写模式:Self-ask Prompt、ReACT与Reflexion

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;自我提问 (Self-ask Prompt)如何工作应用实例优势结论 &#x1f4af;协同思考和动作 (ReACT)如何工作应用实例优势结论 &#x1f4af;失败后自我反思 (Reflexion)如何工作…

oracle数据恢复—文件损坏导致Oracle数据库打开报错的数据恢复案例

oracle数据库故障&分析&#xff1a; 打开oracle数据库时报错&#xff0c;报错信息&#xff1a;“system01.dbf需要更多的恢复来保持一致性&#xff0c;数据库无法打开”。急需恢复zxfg用户下的数据。 出现上述报错的原因有&#xff1a;控制文件损坏、数据文件损坏、数据文件…

FastDFS单节点部署

FastDFS单节点部署 1、FastDFS入门1.1 分布式文件系统1.2 FastDFS 简介1.3 FastDFS 发展历史1.4 FastDFS 整体架构1.5 FastDFS 线上使用者 2、FastDFS 环境搭建2.1 FastDFS 安装2.1.1 安装前的准备2.1.2 安装 libfastcommon库2.1.3 安装 FastDFS 2.2FastDFS 配置2.2.1 去掉/etc…

python爬虫快速入门之---Scrapy 从入门到包吃包住

python爬虫快速入门之—Scrapy 从入门到包吃包住 文章目录 python爬虫快速入门之---Scrapy 从入门到包吃包住一、scrapy简介1.1、scrapy是什么?1.2、Scrapy 的特点1.3、Scrapy 的主要组件1.4、Scrapy 工作流程1.5、scrapy的安装 二、scrapy项目快速入门2.1、scrapy项目快速创建…

Spring Boot框架下JavaWeb在线考试系统的创新实现

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

JavaFx学习--chapter02(网络对话)

chapter02(网络对话) 简单网络对话程序 设计任务&#xff1a;客户端向服务器发送字符串&#xff0c;并能读取服务器返回的字符串。 知识点&#xff1a;TCP套接字技术&#xff0c;C/S软件架构程序设计 重点理解&#xff1a;Java客户套接字类Socket和服务器套接字类ServerSoc…

docker配置加速器

阿里云 控制台》容器镜像服务》镜像工具》镜像加速器 复制地址&#xff1a;https://ywtoq7bz.mirror.aliyuncs.com 到&#xff1a;etc/docker下&#xff1a;vi daemon.json 格式&#xff1a; { "registry-mirrors": ["加速器地址"] } 注&#xff1…

Visual Studio 2022安OpenCV可视化工具image watch

1. 打开 VS2022 &#xff0c;扩展 -管理扩展 2. 搜索 Image Watch 关闭VS2022 后 安装 打开视图、调出 Image Watch 窗口 测试代码&#xff1a; #include "opencv2/imgproc.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.…