再次加深理解Java中的并发编程

目录

一、线程、进程、程序

二、线程状态

三、线程的七大参数

四、lock与synchronized锁机制

一)、lock与synchronized锁区别

二)、synchronized锁原理

三)、Lock锁原理

五、synchronized锁升级原理

一)、锁升级基础知识

二)、锁升级过程有什么用?

三)、synchronized锁升级具体过程

六、Volatile底层原理(可见性和禁止指令重排序)

一)线程安全三要素

二)volatile关键字是如何保证可见性和有序性呢?

三)volatile关键字是线程安全的吗?


一、线程、进程、程序

1.进程: 我们把运行中的程序叫做进程,每个进程都会占用内存与CPU资源,进程与进程之间互相独立,例如360杀毒软件中运行中

2.线程: 线程就是进程中的一个执行单元,负责当前进程中程序的执行。一个进程可以包含多个线程。多线程可以提高程序的并行运行效率。360杀毒软件中的垃圾清理功能

3.程序:是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码,例如360杀毒软件

二、线程状态

1.新建(New):创建线程对象时

2.就绪(Runnable):线程调用start方法,有执行资格没有执行权

3.运行:当就绪状态时抢到cpu的执行权之后,进入运行状态

4.阻塞(Blocked):当获取锁失败后,进入阻塞状态

5.等待(Waiting):等待被notify()方法唤醒

6.休眠(sleep):休眠一段时间,时间到了之后,进入就绪状态。

7.终止(Terminated):线程死亡

注意1:调用start方法方可启动线程,而run方法只是thread类中的一个普通方法调用,还是在主线程里执行。

注意2:wait(long) 和 sleep(long) 的效果都是让当前线程暂时放弃 CPU 的使用权,进入阻塞状态

sleep是Thread的静态方法,而 wait()都是 Object 的成员方法,每个对象都有

sleep方法是暂停当前线程,相当于休眠一段时间,之后会自动唤醒,而wait()必须被notify 或者notifyall方法唤醒,不然会一直阻塞。

Wait会释放锁,sleep不会:wait方法的调用必须先获取wait对象的锁,而sleep则无此限制,wait方法执行后会释放对象锁,允许其它线程获得该对象锁(我放弃 cpu,但你们还可以用);但是如果在 synchronized代码块中执行,并不会释放对象锁(我放弃 cpu,你们也用不了),sleep方法执行后不会释放对象锁。

三、线程的七大参数

1.核心线程数(corePoolSize):表示保持活动状态的最小线程数。

2.最大线程数(maximumPoolSize):表示允许创建的最大线程数。

3.空闲时间(keepAliveTime):表示当线程数量超过核心线程数时,多余的空闲线程能够保持存活的时间。

4.阻塞队列(workQueue):表示用于存储等待执行的任务的阻塞队列。

5.单位(unit):表示空闲时间的单位,例如毫秒、秒等。

6.拒绝策略(rejectedExecutionHandler):表示当任务无法提交给线程池执行时采取的策略。

四、lock与synchronized锁机制

一)、lock与synchronized锁区别

1.语法层面:

1.1.synchronized是关键字,源码在jvm中,用c++ 语言实现

1.2.Lock 是接口,源码由jdk 提供,用java语言实现

2.释放锁机制:

        使用 synchronized 时,退出同步代码块锁会由jvm自动释放锁,比较被动而使用Lock时,需要手动调用unlock方法释放锁,否则可能会导致死锁等问题。

3.都支持可重入锁

        都可以用来控制多个线程访问共享资源的互斥性。都支持可重入锁机制,即同一个线程在已经获得锁的情况下能够再次获取该锁。

4.性能: 

        synchronized适用于简单线程同步场景,Lock适用于高并发场景下,拥有更好的性能和灵活性。

5.synchronized和lock如何保证线程安全?

        synchronized一般情况下通过修饰方法或代码块保证线程安全,而lock一般搭配unlock实现线程安全,lock和unlock中间放需要保证线程安全的代码。但为了避免lock死锁问题,一般将unlock放置于finally代码块中。


//控制方法
public synchronized void sync(){
}

Object lock = new Object();
//控制代码块
public void sync(){
synchronized(lock){

}




Lock lock =new ReentrantLock();

public void sync(){
lock.lock();//上锁
//TODO线程安全的代码
lock.unlock//释放锁,避免死锁

}

二)、synchronized锁原理

        其主要原理是基于Java对象的内部锁,即监视器锁(Monitor Lock),确保在同一时刻只有一个线程可以访问被保护的代码块或方法。当一个线程尝试获取被synchronized关键字保护的资源时,如果该资源已被其他线程占用,该线程就会进入等待状态。占用资源的线程释放该资源时,等待队列中的线程会竞争获取该资源,并且只有一个线程会成功获取到该资源,其他线程继续等待。        

        synchronized关键字保证了可见性和原子性,可见性是通过JVM底层的内存屏障来实现的,原子性则是通过监视器锁的互斥性来实现的。在synchronized块内,线程获得了锁,它将会清空工作内存,从而使得该线程使用的变量能够从主内存中重新读取,同时也会把工作内存中的变量写回到主内存中。这样,其他线程就可以读取到最新的值,从而保证了可见性。

三)、Lock锁原理

        Lock的实现是基于Java的AbstractQueuedSynchronizer(AQS)框架的。Lock接口定义了多个获取和释放锁的方法,其中比较重要的是lock()和unlock()方法。当一个线程调用lock()方法获取锁时,如果锁未被占用,则该线程会占用锁并继续执行;否则,该线程会进入阻塞状态,直到锁被释放。当一个线程调用unlock()方法释放锁时,会通知等待队列中的其他线程继续尝试获取锁。

五、synchronized锁升级原理

一)、锁升级基础知识

1)偏向锁

        只有一个线程争抢锁资源的时候.将线程拥有者标识为当前线程。引入了偏向锁目的是来尽可能减少无竞争情况下的同步操作开销。当一个线程访问同步块并获取对象的锁时,会将锁的标记记录在线程的栈帧中,并将对象头中的Thread ID设置为当前线程的ID。此后,当这个线程再次请求相同对象的锁时,虚拟机会使用已经记录的锁标记,而不需要再次进入同步块。

2)轻量级锁(自旋锁)

        一个或多个线程通过CAS去争抢锁,如果抢不到则一直自旋。虚拟机会将对象的Mark Word复制到线程的栈帧中作为锁记录,并尝试使用CAS自旋操作尝试获取锁。如果CAS成功,则表示线程获取了轻量级锁,并继续执行同步块。如果CAS失败,说明有竞争,虚拟机会通过自旋等待其他线程释放锁。

3)重量级锁

        如果自旋等待不成功,虚拟机会将轻量级锁升级为重量级锁。在这种状态下,虚拟机会将线程阻塞,并使用操作系统的互斥量来实现锁的释放和获取。

        需要注意的是,锁的升级是逐级升级的过程,而不会存在降级。换句话说,一旦锁升级到更高级别,就不会再回到低级别。

二)、锁升级过程有什么用?

1)减少无竞争情况下的同步操作开销

        在多线程环境下,如果没有竞争,每个线程都可以安全地访问共享资源,无需进行同步操作。锁的升级过程中的第一阶段偏向锁(Biased Locking)就是为了在无竞争的情况下减少同步操作的开销。它通过记录线程ID来避免对锁的加锁和解锁操作,提高了单线程访问同步代码块时的性能

2)尽量避免线程切换的开销

        锁的升级过程中的第二阶段轻量级锁(Lightweight Locking)是为了减少线程切换的开销。它使用CAS操作来尝试获取锁,如果成功则可以继续执行同步块,无需线程切换;如果失败,则会进行自旋操作等待锁的释放。自旋操作避免了线程挂起和切换的开销,提高了多线程竞争时的性能

3)降低内存消耗

        锁的升级过程中的第二阶段轻量级锁使用对象头中的一部分位来存储线程ID和锁标记,不需要额外的内存存储锁的状态。相对于传统的重量级锁,它能够节省内存消耗。

4)提高系统吞吐量

        锁的升级过程可以使多个线程在无竞争情况下快速获取锁,避免了线程阻塞和等待的开销。这样,系统的吞吐量会更高,因为更多的线程可以并发地执行任务。

总而言之,锁的升级过程是为了提高多线程环境下的性能和吞吐量,减少同步操作的开销,并尽量避免线程切换的开销。Java虚拟机根据线程竞争的情况和锁的使用情况自动进行锁的升级和降级,以优化多线程程序的性能。

三)、synchronized锁升级具体过程

1)当只有一个线程去争抢锁的时候,会先使用偏向锁,就是给一个标识,说明现在这个锁被线程a占有。
2)后来又来了线程b,线程c,说凭什么你占有锁,需要公平的竞争,于是将标识去掉,也就是撤销偏向锁,升级为轻量级锁,三个线程通过CAS自旋进行锁的争抢(其实这个抢锁过程还是偏向于原来的持有偏向锁的线程).
3)现在线程a占有了锁,线程b,线程c一直在循环尝试获取锁,后来又来了十个线程,一直在自旋,那这样等着也是干耗费CPU资源,所以就将锁升级为重量级锁,向内核申请资源,直接将等待的线程进行阻塞。

六、Volatile底层原理(可见性和禁止指令重排序)

volatile 变量是一种比 sychronized 关键字更轻量级的同步机制。

一)线程安全三要素

原子性:一个操作或者多个操作,要么全部执行成功,要么全部执行失败。满足原子性的操作,中途不可被

中断。

可见性:多个线程共同访问共享变量时,某个线程修改了此变量,其他线程能立即看到修改后的值。

有序性程序执行的顺序按照代码的先后顺序执行。(由于JVM模型中允许编译器和处理器为了效率,进行指令重排序的优化。指令重排序在单线程内表现为串行语义,在多线程中会表现为无序。那么多线程并发编程中,就要考虑如何在多线程环境下可以允许部分指令重排,又要保证有序性)

二)volatile关键字是如何保证可见性和有序性呢?

保证可见性:当一个变量被volatile修饰后,JVM会把工作内存中的最新变量值强制刷新到主内存中,会导致其他线程中的本地缓存失效。这样,其他线程使用缓存时,发现本地工作内存中此变量失效,便会从主内存中获取,这样获取到的值就是最新的值,实现了线程之间可见性

保证有序性:通过编译器在生成字节码时,在指令序列中添加“内存屏障”来禁止指令重排序的,从而保证了有序性。(屏蔽在多线程环境下CPU的指令重排)

三)volatile关键字是线程安全的吗?

        因为volatile保证不了原子性,满足不了线程安全三要素,所以volatile不是线程安全的

值得说明的是,对 volatile 变量的单次读/写操作可以保证原子性的。如 long 和 double 类型变量,
但是并不能保证 i++这种操作的原子性,因为本质上 i++是读、写两次操作。在某些场景下可以代替 Synchronized。但是volatile 的不能完全取代 Synchronized 的位置,只有在一些特殊的场景下,才能适用 volatile。

总的来说,必须同时满足下面两个条件才能保证在并发环境的线程安全:
1、对变量的写操作不依赖于当前值(比如 i++),或者说是单纯的变量赋值(boolean 
flag = true)。
2、该变量没有包含在具有其他变量的不变式中,也就是说,不同的 volatile 变量之间,不
能互相依赖。只有在状态真正独立于程序内其他内容时才能使用 volatile。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

超文本传输协议HTTP

HTTP协议 在网络通信中,我们可以自己进行定制协议,但是也有许多已经十分成熟的应用层协议,比如我们下面说的HTTP协议。 HTTP协议简介 HTTP(Hyper Text Transfer Protocol)协议又叫做超文本传输协议,是一…

JAVAEE之网络编程

1.网络编程 网络编程,指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。 当然,我们只要满足进程不同就行; 所以即便是同一个主机,只要是不同进程&am…

算法学习——LeetCode力扣图论篇1

算法学习——LeetCode力扣图论篇1 797. 所有可能的路径 797. 所有可能的路径 - 力扣(LeetCode) 描述 给你一个有 n 个节点的 有向无环图(DAG),请你找出所有从节点 0 到节点 n-1 的路径并输出(不要求按特…

elementui 导航菜单栏和Breadcrumb 面包屑关联

系列文章目录 一、elementui 导航菜单栏和Breadcrumb 面包屑关联 文章目录 系列文章目录前言一、elementui 导航菜单栏和Breadcrumb 面包屑怎么关联?二、实现效果三、实现步骤1.本项目演示布局2.添加面包屑2.实现breadcrumbName方法3.监听方法4.路由指配5.路由配置…

【C语言】Infiniband驱动mlx4_reset

一、注释 这个 mlx4_reset 函数负责重置 Mellanox 设备。它保存了设备的 PCI 头信息,然后重置了设备,之后还原保存的 PCI 头信息。请注意,该函数是用英文注释的,下面提供中文注释的版本。以下是该函数的流程: 1. 为保…

springboot项目学习-瑞吉外卖(4)续

1.任务 菜品的添加功能(涉及到两张表的数据添加) 2.菜品添加 功能页面如上,该页面有两个注意点 菜品分类:点击菜品分类后,会展示当前已有菜品:这个功能的实现要从category表里查询数据,然后再做展示口味做法配置&#…

SRS OBS利用RTMP协议实现音视频推拉流

参考:https://ossrs.net/lts/zh-cn/docs/v5/doc/getting-started 1)docker直接运行SRS服务: docker run --rm -it -p 1935:1935 -p 1985:1985 -p 8080:8080 registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5运行起来后可以http://localho…

java Web 疫苗预约管理系统用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 JSP 疫苗预约管理系统是一套完善的web设计系统,对理解JSP java 编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发,数据库为Mysql5.0,使…

kaggle竞赛(房价预测)(Pytorch 06)

一 下载数据集 此数据集由Bart de Cock于2011年收集,涵盖了2006‐2010年期间 亚利桑那州 埃姆斯市的房价。 下载地址: import hashlib import os import tarfile import zipfile import requests#save DATA_HUB dict() DATA_URL http://d2l-data.s3…

“崖山数据库杯”深圳大学程序设计竞赛(正式赛)M题 一图秒

“崖山数据库杯”深圳大学程序设计竞赛(正式赛)_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com) —————— 可以去牛客看题解: 题解 | #暂时没想法#_牛客博客 (nowcoder.net) —————— 上面的就是题解了。…

Adobe Illustrator 2023 for Mac/Win:创意无限,设计无界

在数字艺术与设计领域,Adobe Illustrator 2023无疑是一颗璀璨的明星。这款专为Mac和Windows用户打造的矢量图形设计软件,以其强大的功能和卓越的性能,赢得了全球设计师的广泛赞誉。 Adobe Illustrator 2023在继承前代版本优点的基础上&#…

基于ARM内核的智能手环(day1)

整体介绍 智能手环由 ARM 内核 MCU(Cortex-M 系列)、TFTLCD 屏、温湿度传感器、心率传感器、 加速度传感器等主要几部分构成。该平台硬件采用 STM32 芯片,通过对温湿度传感器的驱动编写,获取周围温湿度数据,并在 LCD 屏显示,通过对…

设计模式12--组合模式

定义 案例一 案例二 优缺点

docker配置github仓库ghcr国内镜像加速

文章目录 说明ghcr.io简介配置镜像命令地址命令行方式1panel面板方式方式一:配置镜像加速,命令行拉取方式二:配置镜像仓库,可视化拉取 说明 由于使用的容器需要从github下载镜像,服务器在国外下载速度很慢&#xff0c…

MySQL InnoDB 之 多版本并发控制(MVCC)

多版本并发控制(MVCC,Multi-Version Concurrency Control)是数据库管理系统中用于提供高并发性和在事务处理中实现隔离级别的一种技术。MVCC 允许系统在不完全锁定数据库资源的情况下,处理多个并发事务,从而提高了数据…

计算机网络实验五:特定主机路由和默认路由

实验五:特定主机路由和默认路由 5.1 实验目的 (1)学习默认路由的概念和作用 (2)学习特定路由的概念和作用 (3)了解网络中路由选择的基本原理和应用 5.2 实验步骤 5.2.1 构建网络拓扑 在栏…

LeetCode - 字母板上的路径

1138. 字母板上的路径 刚看到这道题的时候,我居然想用搜索去做这道题,其实有更优解,用 / %算会更加的快,只需要遍历一次即可.假如说我们要找n,n是第13个字母,那他就位于 13 / 5 2, 13 % 5 3.他就位于三行三列(a为0,0),知道了原理,代码就好写了. class Solution { public:st…

基于51单片机HC05蓝牙环境检测系统

目录 1、概要 2、HC05配对传送数据教程 2.1 进入AT模式 2.2串口软件配置 2.3 异常分析 3、代码编写 4、原理图 5、仿真图 6、实物运行视频 7、小结 资料下载地址:基于51单片机手自动浇花系统 1、概要 本文详细介绍HC05蓝牙模块与51单片机的连接配对过程&#xff0c…

【WEEK5】 【DAY5】DML语言【中文版】

2024.3.29 Friday 目录 3.DML语言3.1.外键(了解)3.1.1.概念3.1.2.作用3.1.3.添加(书写)外键的几种方法3.1.3.1.创建表时直接在主动引用的表里写(被引用的表的被引用的部分)3.1.3.2.先创建表后修改表以添加…

二十四种设计模式与六大设计原则(三):【装饰模式、迭代器模式、组合模式、观察者模式、责任链模式、访问者模式】的定义、举例说明、核心思想、适用场景和优缺点

接上次博客:二十四种设计模式与六大设计原则(二):【门面模式、适配器模式、模板方法模式、建造者模式、桥梁模式、命令模式】的定义、举例说明、核心思想、适用场景和优缺点-CSDN博客 目录 装饰模式【Decorator Pattern】 定义…