线程安全2

news2024/10/7 12:23:24

文章目录

  • 锁的可重入性
  • 死锁
  • 内存可见性引起的线程安全

锁的可重入性

在这里插入图片描述
直观来看这个代码不能运行
为啥没有出现阻塞?
当前由于是同一个线程,此时的锁对象,就知道了第二次加锁的线程,就是持有锁的线程,第二次操作,就可以直接放行通过,不会出现阻塞

这个特性称为“可重入”

对于可重入锁来说:内部会持有两个信息
1.当前锁是哪个线程持有的
2.加锁次数的计时器
过程描述:
第一次加锁的时候计数器+1(初始情况为0,+1后变成了1,说明当前这个对象被该线程加锁一次)同时记录线程是谁,第二次加锁的时候,发现加锁线程和持有线程是一个线程,第二次应该能够加锁成功,判断当前加锁进程是否持有锁的线程,如果不是同一个线程,阻塞如果是同一个线程,就只是++计数器,即可没有其他操作,此处的计时器(源码是在JVM中,c++代码实现出来的)是关键。

死锁

1.一个线程,一把锁
如果锁是不可重入锁,并且一个线程对这把锁加锁两次就会出现死锁(钥匙锁屋里了·)

2.两个线程,两把锁
线程1获取到锁A
线程2获取到锁B
接下来,1尝试获取B,2尝试获取A,此时会出现死锁

public static void main(String[] args) {
        Object A = new Object();
        Object B = new Object();
        Thread t1 = new Thread(() -> {
            synchronized (A) {
                // sleep 一下, 是给 t2 时间, 让 t2 也能拿到 B
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 尝试获取 B, 并没有释放 A
                synchronized (B) {
                    System.out.println("t1 拿到了两把锁!");
                }
            }
        });

        Thread t2 = new Thread(() -> {
            synchronized (B) {
                // sleep 一下, 是给 t1 时间, 让 t1 能拿到 A
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 尝试获取 A, 并没有释放 B
                synchronized (A) {
                    System.out.println("t2 拿到了两把锁!");
                }
            }
        });
        t1.start();
        t2.start();
    }
}

3.N个线程M把锁
在这里插入图片描述
在这里插入图片描述
线程一执行到22行
在这里插入图片描述
线程二执行到37行
在这里插入图片描述

在这里插入图片描述
这些线程安全的类也不是绝对的线程安全,只是自带了锁

内存可见性引起的线程安全

public class Test3 {
    private  static int flag = 0;
    public static void main(String[] args) {
        Thread t1 = new Thread(()->{
            while(flag == 0){

            }
            System.out.println("循环结束");
        });
        Thread t2 = new Thread(()->{
            System.out.println("请输入flag的值:");
            Scanner scanner = new Scanner(System.in);
            flag = scanner.nextInt();

        });
        t1.start();
        t2.start();
    }
}

在这个代码中,预期通过t2线程输入的整数,只要输入的不是0,就可以是t1线程结束。
t2要等待用户输入,无论t1先启动还是t2先启动,在等待用户输入的过程中,t1必然循环了很多次了
但是当我们输入非0值,没有输出结果,
原因:内存可见性引起的线程安全,while(flag == 0)由两个指令组成,
1.load读取内存的flag的值到cpu寄存器中
2.拿着寄存器的值与0进行比较
t1线程反复进行1,2操作,由于频繁执行load和条件跳转,load的开销大,并且load的结果又没有变化,此时JVM产生了怀疑,于是JVM就对代码进行了优化,load就被优化掉了,相当于不再重复读内存,直接使用寄存器中之前缓存的值,以提高循环的执行速度,t2修改了内存,但是t1没有看到,就导致了内存可见性问题
为了解决代码优化问题,Java提供了volatile就可以使上述的优化被强制关闭

private volatile static int flag = 0;

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

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

相关文章

一天吃透Java并发面试八股文

内容摘自我的学习网站:topjavaer.cn 分享50道Java并发高频面试题。 线程池 线程池:一个管理线程的池子。 为什么平时都是使用线程池创建线程,直接new一个线程不好吗? 嗯,手动创建线程有两个缺点 不受控风险频繁创…

【WPF.NET开发】WPF中的版式

本文内容 改进的文本质量和性能丰富的版式增强的国际文本支持增强的字体支持新的文本应用程序编程接口 (API) 本主题介绍 WPF 的主要版式功能。 这些功能包括改进的文本呈现质量和性能、OpenType 版式支持、增强的国际文本、增强的字体支持和新的文本应用程序编程接口 (API)。…

SpringMVC RESTful案例

文章目录 1、准备工作2、功能清单3、具体功能:访问首页a>配置view-controllerb>创建页面 4、具体功能:查询所有员工数据a>控制器方法b>创建employee_list.html 5、具体功能:删除a>创建处理delete请求方式的表单b>删除超链接…

多元化的App封装打包平台,解锁应用发布效率

在数字化时代,移动应用已成为连接用户与服务的重要桥梁。对于开发者而言,将应用从代码转化为用户可以直接下载安装的产品,这一过程的效率和质量至关重要。App封装打包平台的出现,为开发者提供了便捷的应用构建、测试和分发解决方案…

Robot Framework之python脚本调用

目录 目录结构 ​编辑 Python函数作为关键字 一、通过Import Library关键字在*** Test Cases ***中引用python脚本 ​编辑 二、通过Library关键字在*** Settings ***中引入python脚本 Python类作为测试库 一、通过Library关键字在*** Settings ***引入python脚本中的类 …

机器学习_7、KNN

数据采用:电离层数据 KNN完整的代码电离层数据资源-CSDN文库 代码 import os import csv import numpy as np from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection import …

DNS域名解析协议

文章目录 DNS域名解析协议一、DNS系统的作用1、DNS的定义2、DNS域名解析2.1 正向解析2.2 反向解析 3、DNS域名结构 二、DNS服务器类型1、主域名服务器2、从域名服务器3、缓存域名服务器4、权威dns服务器 三、DNS查询类型及原理1、查询方式1.1 递归查询1.2 迭代查询 2、DNS查询原…

墙地砖外形检测的技术方案-图像增强

基础理论 本例中使用漫射场光源,在采集图像的过程中,更容易可能会受环境中光源照射不足的可能性,导致采集的图像对比度不足,图像视觉效果较暗。可通过直方图均衡化或者直方图规定化。利用直方图规定化进行图像增强。 案例图片 如…

实例分割论文精读:Mask R-CNN

1.摘要 本文提出了一种概念简单、灵活、通用的实例分割方法,该方法在有效地检测图像中的物体同时,为每个物体实例生成一个实例分割模板,添加了一个分支,用于预测一个对象遮罩,与现有的分支并行,用于边界框…

node各个版本的下载地址

下载地址: https://nodejs.org/dist/ 可以下载多个版本,使用nvm控制切换(需要先安装nvm再安装node) nvm下载地址(访问的是github,请科学上网,下载后解压安装exe即可):h…

【leetcode题解C++】54.螺旋矩阵I and 59.螺旋矩阵II

54.螺旋矩阵I 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例 1: 输入:matrix [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5]示例 2: 输入:m…

通俗易懂实现功能强大的实战项目 springboot+java+vue+mysql 汽车租赁管理系统

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 |…

如何在免费云Colab上使用扩散模型生成图片?

前言 在人工智能技术的迅猛发展下,内容生成领域也迎来了一系列创新的突破。其中,使用扩散模型(如Stable Diffusion)从文字生成图片的AI技术备受瞩目。这一技术的出现,为我们创造栩栩如生的图像提供了全新的可能性。本…

ceph、gluster、longhorn选型对比

Ceph Ceph是一个分布式的存储系统,可以在统一的系统中提供唯一的对象、块和文件存储。 名词解释: RADOS: 由自我修复、自我管理、智能存储节点组成的可靠、自主、分布式对象存储LIBRADOS: 一个允许应用程序直接访问 RADO 的库&…

机器学习 | 无监督聚类K-means和混合高斯模型

机器学习 | 无监督聚类K-means和混合高斯模型 1. 实验目的 实现一个K-means算法和混合高斯模型,并用EM算法估计模型中的参数。 2. 实验内容 用高斯分布产生 k k k个高斯分布的数据(不同均值和方差)(其中参数自己设定&#xff…

网络分流规则

现在的网络是越来越复杂。 有必要进行分流。 有一些geosite.dat是已经整理好的,包含许多的网站的分类: 分流规则: route规则 主要是: {"type": "field","outboundTag": "direct","domain&quo…

【Windows】你不能访问此共享文件夹,因为你的组织安全策略...解决方法

WinR键打开运行窗口,输入gpedit.msc进入本地组策略编辑器。 找到计算机配置,然后点击管理模板,找到网络,然后点击lanman工作站,将右侧窗口中的启用不安全的来吧登录开启就解决了 设置为已启用,应用后确定&a…

定时器--JAVA

定时器是软件开发中的一个重要组件,类似于一个"闹钟"当达到一个设定的时间之后,就执行某个指定好的代码(任务)。 Timer JAVA标准库中已经为我们实现了一个定时器,我们直接new就行了。 Timer timer new Timer(); Timer类中最重要的一个方法…

Fine-tuning:个性化AI的妙术

随着人工智能(AI)技术的迅猛发展,Fine-tuning作为一项重要而神奇的技术崭露头角。Fine-tuning俗称“微调技术。其本质上是对已有模型进行能力的迁移学习扩展,由于重新训练神经网络模型的成本太高,所以使用微调技术可以…

GZ075 云计算应用赛题第8套

2023年全国职业院校技能大赛(高职组) “云计算应用”赛项赛卷8 某企业根据自身业务需求,实施数字化转型,规划和建设数字化平台,平台聚焦“DevOps开发运维一体化”和“数据驱动产品开发”,拟采用开源OpenSt…