多线程——线程安全

线程安全问题

同时满足以下两个条件时:

  1. 多个线程在操作共享的数据。
  2. 操作共享数据的线程代码有多条。

当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会导致线程安全问题的产生。
解决这样的问题就是线程同步的方式来实现。

线程同步

同步就是协同步调,按预定的先后次序进行运行
不是同时进行,指协同、协助、互相配合。与异步相反。
线程同步是指多线程通过特定的设置在线程之间通过同步建立起执行顺序的关系,如果没有同步,那线程之间是各自运行各自的!

同步方式

1. 同步代码块

即有synchronized关键字修饰的语句块。

被该关键字修饰的语句块会自动被加上内置锁,被保护的语句代码所在的线程要执行,需要获得内置锁,否则就处于阻塞状态。

synchronized(object){}

括号里的这个对象可以是任意对象,这个对象一般称为同步锁

同步的前提:同步中必须有多个线程并使用同一个锁。

同步的好处:解决了线程的安全问题。

**注:**同步是一种高开销的操作,因此应该尽量减少同步的内容。

通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。

public void run() {while (true) {synchronized (obj) {	if (tickets > 0) {try {Thread.sleep(10);} catch (InterruptedException e) {}System.out.println(Thread.currentThread().getName() + "....sale...." + tickets--);}else {break;}}}}
2. 同步方法

即有synchronized关键字修饰的方法。
由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,
内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。

public synchronized void aa(){}

对于普通同步方法,锁是当前实例对象。
对于静态同步方法,锁是当前类的Class对象。
对于同步方法块,锁是Synchonized括号里配置的对象。

3. 使用重入锁

在JDK1.5中新增了一个java.util.concurrent包来支持同步。使用JUC里的Lock与使用synchronized方法和块具有相同的基本行为和语义,并且扩展了其能力前面讲了关键字synchronized实现的同步的锁,是隐藏的,所以我们并不明确是在哪里加上了锁,在哪里释放了锁。

为了更明确的控制从哪里开始锁,在哪里释放锁,JDK1.5提供了Lock。 Lock是一个接口,我们真正用的是它的实现类ReentrantLock。

ReenreantLock类的常用方法有:

ReentrantLock() : 创建一个ReentrantLock实例 lock() : 获得锁
unlock() : 释放锁

public class Sell implements Runnable { private int tickets = 100;private	Lock lock = new ReentrantLock(); @Overridepublic void run() { while(true) {lock.lock(); try {if(tickets > 0) {System.out.println(Thread.currentThread().getName() + "正在出票**...**	" + tickets--);try { Thread.sleep(10);} catch (InterruptedException e) { throw new RuntimeException(e);}}else {break;}}finally {lock.unlock();}}}}

在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

4. 使用局部变量

如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。

ThreadLocal

ThreadLocal():创建一个线程本地变量
get() : 返回此线程局部变量的当前线程副本中的值
initialValue() : 返回此线程局部变量的当前线程的"初始值"
set(T value) : 将此线程局部变量的当前线程副本中的值设置为value

public class ThreadTest {public static void main(String[] args) {SychronizedThread st = new SychronizedThread();new Thread(st, "线程1").start();new Thread(st, "线程2").start();new Thread(st, "线程3").start();new Thread(st, "线程4").start();}
}class SychronizedThread implements Runnable {private static ThreadLocal<Integer> ticketNumber = ThreadLocal.withInitial(() -> 10);@Overridepublic void run() {while (true) {if (ticketNumber.get() > 0) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程" + Thread.currentThread().getName() + "售出第" + ticketNumber.get() + "号票");ticketNumber.set(ticketNumber.get() - 1);} else {break;}}}
}
  1. ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题。
  2. ThreadLocal并不能代替同步机制,两者面向的问题领域不同。同步机制是为了同步多个线程对相同资源的并发访问,是多个线程之间进行通信,并且协同的有效方式;而 ThreadLocal是为了隔离多个线程的数据共享,从而避免多个线程之间对共享资源的竞争,也就不需要对多个线程进行同步了。ThreadLocal采用以"空间换时间"的方法,其他同步机制采用以"时间换空间"的方式。
  3. ThreadLocal适用的场景是:多个线程都需要使用一个变量,但这个变量的值不需要在各个线程间共享,各个线程都只使用自己的这个变量的值。这样的场景下,可以使用ThreadLocal。
总结

前面我们用关键字synchronized构成同步代码块和同步方法,来实现多线程的同步,本质上我们可以理解为底层的程序给线程加了一把我们看不见的隐藏的锁,只有获取到这把锁的线程才能被执行,没拿到的线程你就给我等着,从而控制线程的执行顺序,达到同步效果。所以,任何线程进入同步代码块、同步方法之前,必须先获得对于同步监测器的锁定,那么谁会释放对同步监测器的锁定呢?

在Java中,程序无法显式的释放对同步监测器的锁定,释放权在底层的JVM上,JVM会从释放机制中自动的释放。

释放同步监测器锁定

  1. 当前线程的同步方法、同步代码块执行结束,当前线程即释放随同步监测器的锁定;
  2. 当前线程的同步方法、同步代码块中遇到break、return终止了该代码块、方法的继续执行,当前线程会释放同步监测器的锁定;
  3. 当前线程在同步方法、同步代码块中出现了未处理的error或者exception,导致了该代码块、该方法异常结束时,当前线程会释放同步监测器的锁定;
  4. 当前线程执行同步代码块或同步方法时,程序调用了同步监测器的wait()方法,当前线程暂停,则当前线程会释放同步监测器的锁定。

不释放对同步监测器的锁定:

  1. 线程执行同步代码块或者同步方法时,程序调用了Thread.sleep()、Thread.yield()方法来暂停当前线程执行,当前线程不会释放对同步监测器的锁定;
  2. 线程执行同步代码块时,其他线程调用了该线程的suspend()方法(suspend会阻塞线程直到另一个线程调用resume,这个方法容易死锁,已经不推荐使用了,了解一下就ok)将该线程挂起,也不会释放同步监测器的锁定。

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

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

相关文章

揭秘Taboola原生广告:欧美流量变现联盟营销金牌策略

揭秘Taboola原生广告&#xff1a;欧美流量变现的金牌策略 在数字营销日益精进的今天&#xff0c;如何高效地将网站流量转化为实际收益成为了众多欧美网站主关注的焦点。Taboola&#xff0c;作为原生广告领域的佼佼者&#xff0c;凭借其独特的广告展示方式与强大的数据驱动能力…

判断两个yaw角度之差是否超过了90度

一. 判断两个yaw角度之差是否超过了90度 要判断两个 yaw 角度之差是否超过 90 度&#xff0c;你可以通过计算这两个角度的差值&#xff0c;并将其归一化为 [-180, 180] 的范围内。接着&#xff0c;只需判断该差值的绝对值是否大于 90 度。 实现步骤&#xff1a; 计算角度差&…

上海晋名室外危化品暂存柜助力新能源行业发展

近日又有一个SAVEST室外危化品暂存柜项目成功验收交付使用。 用户在日常经营活动中涉及到气瓶和硅粉的室外安全暂存问题&#xff0c;4月下旬在网上看到上海晋名室外暂存柜系列很感兴趣&#xff0c;联系到了销售部钟经理&#xff0c;双方对晋名的室外暂存柜进行了高效的沟通&am…

无人机+应用综合实训室解决方案

随着无人机技术的飞速发展&#xff0c;其在航拍、农业、环境监测、物流运输等多个领域展现出巨大的应用潜力。为了满足职业院校及企业对无人机应用技术型人才的培养需求&#xff0c;唯众紧跟市场趋势&#xff0c;推出了全面且详尽的《无人机应用综合实训室解决方案》。本方案旨…

MACOS安装配置前端开发环境

官网下载安装Mac版本的谷歌浏览器以及VS code代码编辑器&#xff0c;还有在App Store中直接安装Xcode&#xff08;里面自带git&#xff09;&#xff1b; node.js版本管理器nvm的下载安装如下&#xff1a; 参考B站&#xff1a;https://www.bilibili.com/video/BV1M54y1N7fx/?sp…

【学习AI-相关路程-工具使用-自我学习-jetson模型训练-图片识别-使用模型检测图片-基础样例 (5)】

【学习AI-相关路程-工具使用-自我学习-jetson&模型训练-图片识别-使用模型检测图片-基础样例 &#xff08;5&#xff09;】 1 -前言2 -环境说明3 -先行了解&#xff08;1&#xff09;整理流程了解&#xff08;2&#xff09;了解模型-MobileNet1、MobileNetV2 的主要特性&am…

python源码 PBOCMaster MAC的计算函数及计算过程 2des

注意最后一步要用整个key加密 计算过程&#xff1a; MAC&#xff1a; PBOC-MAC DES算法 密钥 长度16(0x10)字节 57 75 20 4D 69 61 6F 6A 75 6E 40 47 26 44 43 11 初始向量 长度8(0x08)字节 00 00 00 00 00 00 00 00 数据 长度74(0x4A)字节 43 48 45 4E 48 41 4F 2D 50 43 7…

Python股票接口实现量化交易的优势是什么

炒股自动化&#xff1a;申请官方API接口&#xff0c;散户也可以 python炒股自动化&#xff08;0&#xff09;&#xff0c;申请券商API接口 python炒股自动化&#xff08;1&#xff09;&#xff0c;量化交易接口区别 Python炒股自动化&#xff08;2&#xff09;&#xff1a;获取…

MSP430F149实现1.8寸TFT_LCD真彩屏显示

目录 一、功能实现 二、设备准备 三、接线表设计 四、代码实现 五、实现效果 六、代码链接 一、功能实现 实现1.8寸TFT_LCD真彩屏显示。显示数字、图片、字符串等。 二、设备准备 1.TFT_LCD真彩屏&#xff08;1.8寸&#xff09; 该真彩屏使用SPI通信。 2.MSP430F149开…

CSRF,SSRF和重放攻击的区别

CSRF是跨站请求伪造攻击&#xff0c;由客户端发起 SSRF是服务器端请求伪造&#xff0c;由服务器发起 重放攻击时将截获的数据包进行重放&#xff0c;达到身份认证等目的 三种是不同的网络安全攻击方式&#xff0c;他们在攻击方式&#xff0c;目标&#xff0c;影响以及防御策略…

微服务CI/CD实践(五)Jenkins Docker 自动化构建部署Node服务

微服务CI/CD实践系列&#xff1a; 微服务CI/CD实践&#xff08;一&#xff09;环境准备及虚拟机创建 微服务CI/CD实践&#xff08;二&#xff09;服务器先决准备 微服务CI/CD实践&#xff08;三&#xff09;gitlab部署及nexus3部署 微服务CI/CD实践&#xff08;四&#xff09…

【软件设计】常用设计模式--策略模式

软件设计模式&#xff08;三&#xff09; 策略模式&#xff08;Strategy Pattern&#xff09;1. 概念2. 模式结构3. UML 类图4. 实现方式C# 示例步骤1&#xff1a;定义策略接口步骤2&#xff1a;实现具体策略类步骤3&#xff1a;实现上下文类步骤4&#xff1a;使用策略模式 Jav…

.NET/C#⾯试题汇总系列:基础语法

1. 字符串中string strnull和string str""和string strstring.Empty的区别&#xff1f; string str null;&#xff1a;这种方式声明了一个字符串变量str&#xff0c;并将其初始化为null。这意味着str不指向任何实际的字符串对象。如果你试图访问str的属性或方法&…

HTTPS SEO优势

搜索引擎优化&#xff08;SEO&#xff09;是提高网站在搜索引擎结果页&#xff08;SERP&#xff09;中的排名以吸引更多访问者的过程。HTTPS作为网站安全的标准&#xff0c;对SEO有着直接和间接的优势&#xff1a; 1. HTTPS作为排名信号 2014年&#xff0c;Google宣布HTTPS成…

穿越机的应用行业!!!

1. 军事领域 侦察与目标搜索&#xff1a;穿越机能够快速穿越危险区域&#xff0c;执行侦察任务&#xff0c;实时获取战场信息&#xff0c;对敌方目标进行精确搜索和定位。其灵活性和机动性使其成为战场上的重要侦察工具。 目标摧毁&#xff1a;经过改装的穿越机可挂载火箭弹或…

华三防火墙第-安全策略02

一 安全策略的图解 安全策略是一种根据报文的属性信息对报文进行精细化转发控制的智能安全防护措施。它 融合了多维度精确报文识别、深度报文检测、安全动作执行、智能策略分析、应用风险调 优等多种安全防护功能,为网络的安全性提供全方位保障。 安全策略运行原理 安全策略对…

CSS实现文字环绕圆形展示

展示区域 代码区域 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><s…

ubuntu20.04搭建kubernetes1.28.13集群配置calico网络插件

写在前面 这里是我在搭建过程中从某站找到的教学视频,搭载的都是最新的,大家可以参考一下 搭建kubernetes集群学习视频: 视频链接。最后面会有我遇见报错信息的所有连接和解决方案,自行查看 不说废话,直接开搭 搭建集群大纲 一、三台虚拟机的初始化 二、三台虚拟机连接…

[240905] 如何使用 JAX 和 Equinox 构建图卷积网络 | Cascadia 字体家族迎来新成员

目录 如何使用 JAX 和 Equinox 构建图卷积网络1 使用邻接矩阵1.1 邻接矩阵表示法1.2 图卷积层实现1.3 计算过程解释 2 使用边列表2.1 边列表表示法2.2 图卷积层实现2.3 代码解析&#xff1a;jax.ops.segment_sum2.4 计算节点度数示例2.5 边列表表示法的优势 3 模型训练3.1 任务…

VTK平面切割

文章目录 一、vtkClipPolyData二、CapClip三、SolidClip四、vtkClipClosedSurface 本文的主要内容&#xff1a;简单介绍VTK中通过平面切割模型的相关功能。 哪些人适合阅读本文&#xff1a;有一定VTK基础的人。 一、vtkClipPolyData VTK官网描述&#xff1a; vtkClipPolyData使…