多线程---锁

锁的概述

参考视频:1-2 锁概述哔哩哔哩bilibili

线程安全问题的产生前提是多个线程并发访问共享数据

将多个线程对共享数据的并发访问转换为串行访问,即一个共享数据一次只能被一个线程访问。所就是复用这种思路来保障线程安全的

锁(lock)可以理解为对共享数据进行保护的一个许可证。对于同一个许可证保护的共享数据来说,任何线程想要访问这些共享数据必须先持有该许可证。一个线程只有在持有许可证的情况下才能对这些共享数据进行访问。

一个线程在访问共享数据前必须先获得锁,获得锁的线程称为锁的持有线程;一个锁一次只能被一个线程持有,锁的持有线程在获得锁之后和释放锁之前这段时间所执行的代码被称为临界区(Critical Section)。

锁具有排他性(Exclusive),即一个锁一次只能被一个线程持有,这种锁被称为排它锁或互斥锁。

JVM把锁分为内部锁和显示锁两种。内部锁通过synchronized关键词实现;显示锁通过java.concurrent.locks.Lock接口实现

 

锁的作用

  锁可以实现对共享数据的安全访问,保障线程的原子性,可见性与有序性

  锁是通过互斥保障原子性,一个锁只能被一个线程持有,这就保证临界区的代码一次只能被一个线程执行。使得临界区代码所执行的操作自然而然的具有不可分割的特性,即具备了原子性。

  可见性的保障是通过写线程冲刷处理器的缓存和读线程刷新处理器缓存这两个动作实现的。在Java平台中,锁的获得隐含着刷新处理器缓存的动作,锁的释放隐含着冲刷处理器缓存的动作。(注:可见性:下一个线程加锁后可以看到所有前一个线程解锁前发生的所有操作)

  锁能够保障有序性,写线程在临界区所执行的在读线程所执行的临界区看来像是完全按照源码顺序执行的。

注意:

使用锁保障线程的安全性,必须满足以下条件:

  1.这些线程在访问共享数据时必须使用同一个锁

  2.即使能读取共享数据的线程也需要使用同步锁

 

1.可重入性

  可重入性(Reentrancy):一个线程持有该锁的时候能再次(多次)申请该锁。

  如果一个线程持有一个锁的时候还能够继续成功申请该锁,称该锁是可重入的,否则就称该锁为不可重入。

2.锁的争用与调用

  Java平台中内部锁属于非公平锁,显示Lock锁既支持公平锁又支持非公平锁

3.锁的粒度

  一个锁可以保护的共享数据的数量大小称为锁的粒度

  锁保护共享数据量大,称为锁的粒度粗,否则就称该锁的粒度细

  锁的粒度过粗会导致线程在申请锁时会进行不必要的等待。锁的粒度过细会增加锁调度的开销。

 

内部锁:synchronized()

显示锁:lock()

posted @   默夔然  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~
点击右上角即可分享
微信分享提示