JavaEE初阶多线程 (5)

1.锁的策略

1.1锁的策略是什么

这个锁的策略可以理解为,一种做法,相当于当你遇到锁竞争,加锁解锁,的情况你会怎么做。

乐观锁可以理解为疫情的时候比较乐观就买了最基本的物资, 买的时候非常方便

1.2乐观锁

当效率冲突比较低的时候就是乐观锁,这个锁就是乐观锁,资源占用率小

1.3悲观锁

当效率冲突较高的时候就是悲观锁,这个锁就是悲观锁,资源占用率高

1.4悲观锁和乐观锁的对比

1.5轻量级锁

轻量级锁就是☞任务比较少,加锁的数量较少,可以大概理解为乐观锁

1.6重量级锁

重量级锁就是☞任务比较多,加锁的数量比较少,可以理解为悲观锁

1.7轻量级锁和重量级锁的对比

1.8synconize锁

这个是Java包中的锁,他是比较只智能的任务少的时候就是乐观锁,任务多的时候就是悲观锁。

1.9自旋锁

一种轻量级锁的实现方式(典型)

类似于你追你女神结果女神有对象然后你一直每天骚扰,然后这时候女神分手了,这时候你就上位了,这时候就是自旋锁的感觉。

代码图片

1.10挂起等待锁

一种重量级锁的实现方式(典型)

类似于你追女神然后女神有对象,这时候你微信把女神拉黑,然后一直默默努力,然后这时候女神分手了,然后你再追求女神,这个中间空白的时间就是(挂起时间)

1.11可重入锁

synchronized就是一个可重入锁它可以一直不断的给一个对象进行加锁,不会发生死锁

1.12不可重入锁

在C++中std:mutex就是一个不可重入锁,针对一格线程加锁两次就会发生死锁。

1.13公平锁

严格按照先来后到的顺序来获取锁,哪个线程的等待时间长就是哪个线程获得锁

1.14非公平锁

各个线程各凭本事,谁拿到锁这个就是谁的。

其中synconize不是公平锁,他是系统随机调度的,要是想公平的化就要使用队列来实现线程的公平拿到锁。

1.15公平锁和非公平锁的相互功能对比

1.16互斥锁

互斥锁相当于拿到这个锁以后如果这个线程再出现一次这个锁就会报错,像synconize就是一个典型的互斥锁

1.17读写锁(JAVA api中读写锁来让我们用)

我画了一格逻辑图来让大家更好的了解到读写锁是什么东西

2.synconize详细讲解

在上面讲了那么多的锁,我们一定好奇在java jdk包中提供的synconize是什么锁这里我就总结一下

synconize其实是一个自适应的锁

它加锁的状态是下面这一张图片

这个偏向锁相当一个标记,如果需要加锁他就会加锁,如果不需要加锁他就一直标记着知道这个线程结束。在下面的图中,升级的过程是不可逆的。未来JVM或许会出一个这样的功能

3.JVM处理锁

3.1synconize锁的优化

(synconize)在编译器中,JVM会自动来判断这个锁是否应该存在,如果需要加锁就保留不需要就直接消除。

4.CAS流程

CAS是compare 和swap进行比较和交换的意思

这是CPU的原子命令

其中JVM把这个CPU的原子指令给封装所以我们可以用这个原子指令,来进行CAS的操作

这个不建议大家用容易出错

这里只是给大家讲解一下

我们还可以用这种封装的方法来替换运算符

其中这些被封装的方法是没有进行加锁的因为加锁的化就会占用CPU占用CPU就会使代码的效率降低。

这些方法只能在一些特定的场景下才能使用

4.1CAS可能出现的BUG

4.1.1CAS描述BUG背景

出现BUG的场景是银行取钱,你点了好几次然后取款机的按钮卡了一下,然后由于你多点了几次所以导致你出现了多个线程,假设有两个线程。然后还有一个线程是你朋友给你打了500块。

打钱的线程我们称为t1 那两个线程称之为t1 ,t2.

这个是取钱的线程

CAS是用来判断现在的和以前的钱的数值是否一样

4.1.2CAS样例代码

(1) 这段diamond的意思是定义了一个变量是oldBalance这个是用来记录现在我们的银行卡的当前余额的

(2)其中CAS操作是用来比较和赋值的,如果balance和oldbalance是相同的说明没有其他线程对balance来进行操作,这时候就会发生扣款操作,然后扣款以后的值就会等价到balance中,然后这时候oldbalance也会进行更新,假设balance的大小是1000这时候就会变成500。

4.1.3代码发生BUG图解

这时候就会发现虽然还是1000块其实已经扣款了1000(应该扣款的金额是500但是扣款了1000)

4.2 CAS的BUG的解决方式

4.2.1引入版本号问题来解决BUG

(1)引入一个版本号,这个版本中只能进行加或者只能减,当执行了这个操作以后这个版本号就会加一。

(2)这样就可以很好的避免CAS问题

5.Callable类解决线程耦合性的问题

5.1代码

(1)和主线程高度耦合的代码

上面的这段代码的耦合性太强了这会导致我们在未来维护项目的时候不好维护。

为了能够降低线程和线程之间的耦合程度,我们引入了callable这个来降低各个线程之间的耦合程度。

5.2代码实例

这个有两个部分相当于是异步编程

这样就是可以很好的降低了代码的耦合度

6.多线程创建的几种方法

7.多线程的知识扩展

7.1Semaphore(信号量)

(1)信号量就是相当于计数器

7.2ReenTrantLock(可重入锁)(已经淘汰了)

在以前sychronized是没有那么好

7.3countDownLatch(拆分扫描任务)

7.4countDownLock(锁存器)

这个可以用来代替join

8.线程安全

8.1多线程下的数据结构

8.1队列保证线程的安全

ConcurrenHashMap(重点)

8.3复制来队列来保证多线程读写时的安全

相关推荐
浪里个浪的1024几秒前
【C语言】计算3x3矩阵每行的最大值并存入第四列
c语言·开发语言·矩阵
@东辰8 分钟前
【golang-技巧】-自定义k8s-operator-by kubebuilder
开发语言·golang·kubernetes
Hello-Brand8 分钟前
Java核心知识体系10-线程管理
java·高并发·多线程·并发·多线程模型·线程管理
乐悠小码14 分钟前
数据结构------队列(Java语言描述)
java·开发语言·数据结构·链表·队列
史努比.16 分钟前
Pod控制器
java·开发语言
2的n次方_19 分钟前
二维费用背包问题
java·算法·动态规划
皮皮林55119 分钟前
警惕!List.of() vs Arrays.asList():这些隐藏差异可能让你的代码崩溃!
java
莳光.19 分钟前
122、java的LambdaQueryWapper的条件拼接实现数据sql中and (column1 =1 or column1 is null)
java·mybatis
程序猿麦小七24 分钟前
基于springboot的景区网页设计与实现
java·spring boot·后端·旅游·景区
敲敲敲-敲代码25 分钟前
游戏设计:推箱子【easyx图形界面/c语言】
c语言·开发语言·游戏