【多线程】synchronized 关键字 - 监视器锁 monitor lock

synchronized

  • 1 synchronized 的特性
    • 1) 互斥
    • 2) 可重入
  • 2 synchronized 使用示例
    • 1) 修饰代码块: 明确指定锁哪个对象.
    • 2) 直接修饰普通方法: 锁的 SynchronizedDemo 对象
    • 3) 修饰静态方法: 锁的 SynchronizedDemo 类的对象
  • 3 Java 标准库中的线程安全类

1 synchronized 的特性

1) 互斥

synchronized 会起到互斥效果, 某个线程执⾏到某个对象的 synchronized 中时, 其他线程如果也执⾏
到同⼀个对象 synchronized 就会阻塞等待.

• 进⼊ synchronized 修饰的代码块, 相当于 加锁
• 退出 synchronized 修饰的代码块, 相当于 解锁

在这里插入图片描述
synchronized⽤的锁是存在Java对象头⾥的
在这里插入图片描述
可以粗略理解成, 每个对象在内存中存储的时候, 都存有⼀块内存表⽰当前的 “锁定” 状态(类似于厕所
的 “有⼈/⽆⼈”).
如果当前是 “⽆⼈” 状态, 那么就可以使⽤, 使⽤时需要设为 “有⼈” 状态.
如果当前是 “有⼈” 状态, 那么其他⼈⽆法使⽤, 只能排队
在这里插入图片描述
理解 “阻塞等待”.

针对每⼀把锁, 操作系统内部都维护了⼀个等待队列. 当这个锁被某个线程占有的时候, 其他线程尝试
进⾏加锁, 就加不上了, 就会阻塞等待, ⼀直等到之前的线程解锁之后, 由操作系统唤醒⼀个新的线程,
再来获取到这个锁.

注意:
• 上⼀个线程解锁之后, 下⼀个线程并不是⽴即就能获取到锁. ⽽是要靠操作系统来 “唤醒”. 这也就
是操作系统线程调度的⼀部分⼯作.
• 假设有 A B C 三个线程, 线程 A 先获取到锁, 然后 B 尝试获取锁, 然后 C 再尝试获取锁, 此时 B 和 C
都在阻塞队列中排队等待. 但是当 A 释放锁之后, 虽然 B ⽐ C 先来的, 但是 B 不⼀定就能获取到锁,
⽽是和 C 重新竞争, 并不遵守先来后到的规则.

synchronized的底层是使⽤操作系统的mutex lock实现的.

2) 可重入

synchronized 同步块对同⼀条线程来说是可重⼊的,不会出现⾃⼰把⾃⼰锁死的问题;

理解 “把⾃⼰锁死”
⼀个线程没有释放锁, 然后⼜尝试再次加锁.
// 第⼀次加锁, 加锁成功
lock();
// 第⼆次加锁, 锁已经被占⽤, 阻塞等待.
lock();
按照之前对于锁的设定, 第⼆次加锁的时候, 就会阻塞等待. 直到第⼀次的锁被释放, 才能获取到第⼆
个锁. 但是释放第⼀个锁也是由该线程来完成, 结果这个线程已经躺平了, 啥都不想⼲了, 也就⽆法进
⾏解锁操作. 这时候就会 死锁。

在这里插入图片描述

Java 中的 synchronized 是 可重⼊锁, 因此没有上⾯的问题.

for (int i = 0; i < 50000; i++) {
 synchronized (locker) {
 synchronized (locker) {
 count++;
 }
 }
}

在可重⼊锁的内部, 包含了 “线程持有者” 和 “计数器” 两个信息.

• 如果某个线程加锁的时候, 发现锁已经被⼈占⽤, 但是恰好占⽤的正是⾃⼰, 那么仍然可以继续获取到锁, 并让计数器⾃增. •
解锁的时候计数器递减为 0 的时候, 才真正释放锁. (才能被别的线程获取到)

2 synchronized 使用示例

synchronized 本质上要修改指定对象的 “对象头”. 从使⽤⻆度来看, synchronized 也势必要搭配⼀个具体的对象来使⽤.

1) 修饰代码块: 明确指定锁哪个对象.

锁任意对象

public class SynchronizedDemo {
 private Object locker = new Object();
 
 public void method() {
 synchronized (locker) {
 
 }
 }
}

锁当前对象

public class SynchronizedDemo {
 public void method() {
 synchronized (this) {
  }
 }
}

2) 直接修饰普通方法: 锁的 SynchronizedDemo 对象

public class SynchronizedDemo {
 public synchronized void methond() {
 }
}

3) 修饰静态方法: 锁的 SynchronizedDemo 类的对象

public class SynchronizedDemo {
 public synchronized static void method() {
 }
}

我们重点要理解,synchronized 锁的是什么. 两个线程竞争同⼀把锁, 才会产⽣阻塞等待.

两个线程分别尝试获取两把不同的锁, 不会产⽣竞争.

在这里插入图片描述

3 Java 标准库中的线程安全类

Java 标准库中很多都是线程不安全的. 这些类可能会涉及到多线程修改共享数据, ⼜没有任何加锁措施.

• ArrayList
业课
• LinkedList
• HashMap
• TreeMap
• HashSet
• TreeSet
• StringBuilder

但是还有⼀些是线程安全的. 使⽤了⼀些锁机制来控制.

• Vector (不推荐使⽤)
• HashTable (不推荐使⽤)
• ConcurrentHashMap
• StringBuffer

在这里插入图片描述

StringBuffer 的核⼼⽅法都带有 synchronized .

还有的虽然没有加锁, 但是不涉及 “修改”, 仍然是线程安全的。

• String

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

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

相关文章

信号通信与消息队列实现的通信:2024/2/23

作业1&#xff1a;将信号和消息队列的课堂代码敲一遍 1.1 信号 1.1.1 信号默认、捕获、忽略处理(普通信号) 代码&#xff1a; #include <myhead.h> void handler(int signo) {if(signoSIGINT){printf("用户键入 ctrlc\n");} } int main(int argc, const ch…

招聘APP开发实践:技术选型、架构设计与开发流程

时下&#xff0c;招聘APP成为了企业和求职者之间连接的重要纽带。本文将深入探讨招聘APP的开发实践&#xff0c;重点关注技术选型、架构设计以及开发流程等关键方面&#xff0c;带领读者走进这一充满挑战与机遇的领域。 一、技术选型 在开始招聘APP的开发之前&#xff0c;首…

单片机51 输入和输出

一、IO口基本概念介绍 单片机的IO口&#xff08;Input/Output口&#xff09;是连接单片机与外部电路或设备的接口。单片机的IO口可以分为输入口和输出口两种&#xff0c;用于控制和监测外部设备的状态。 1. 输入口&#xff1a;单片机的输入口用于接收外部电路或设备的信号。输…

Day20_网络编程(软件结构,网络编程三要素,UDP网络编程,TCP网络编程)

文章目录 Day20 网络编程学习目标1 软件结构2 网络编程三要素2.1 IP地址和域名1、IP地址2、域名3、InetAddress类 2.2 端口号2.3 网络通信协议1、OSI参考模型和TCP/IP参考模型2、UDP协议3、TCP协议 2.4 Socket编程 3 UDP网络编程3.1 DatagramSocket和DatagramPacket1、Datagram…

2024年 最新python调用ChatGPT实战教程

2024年 最新python调用ChatGPT实战教程 文章目录 2024年 最新python调用ChatGPT实战教程一、前言二、具体分析1、简版程序2、多轮对话3、流式输出4、返回消耗的token 一、前言 这个之前经常用到&#xff0c;简单记录一下,注意目前chatgpt 更新了&#xff0c;这个是最新版的&am…

linux中的权限

Linux 的权限 在了解Linux的权限之前&#xff0c;我们需要知道Linux的构成&#xff0c;Linux分为三个部分&#xff0c;内核、外部程序、以及用户。 内核&#xff1a; 内核一般是指Linux的操作系统&#xff0c;用来执行用户发送的指令 或者 拒绝执行用户发布指令时而发出的报…

07_html

文章目录 引言前端概述分类 HTML快速入门重要的body标签注释hr标签br标签一些常见的标签标题标签div标签span标签p标签a标签img标签路径问题 ol和ul标签table标签input标签&#xff08;表单元素&#xff09;textarea标签&#xff08;表单元素&#xff09;select标签&#xff08…

使用Lombok @Data 出现java: 找不到符号 的问题

第一种&#xff1a;pom依赖最好如下方式 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>RELEASE</version><scope>compile</scope> </dependency>第二种&#xff1…

在项目中应用设计模式的实践指南

目录 ✨✨ 祝屏幕前的您天天开心&#xff0c;每天都有好运相伴。我们一起加油&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 引言 一. 单例模式&#xff08;Singleton Pattern&#xff09; 1、实现单例模式的方式 1…

neo4j创建新数据库

根据网上提供的教程&#xff0c;neo4j并没有提供创建数据库的命令&#xff0c;其只有一个默认数据库graph.db&#xff0c;该数据库中的所有数据将存储在neo4j安装路径下的data/databases/graph.db目录中。 因此&#xff0c;我们猜想&#xff0c;如果我们将默认数据库的名字修改…

【Vue渗透】Vue Devtools 浏览器插件

下载地址 Vue Devtools 浏览器插件 Vue站点渗透思路 【Vue渗透】Vue站点渗透思路 简介 Vue Devtools 是 Vue 官方发布的调试浏览器插件&#xff0c;可以安装在 Chrome 和 Firefox 等浏览器上&#xff0c;直接内嵌在开发者工具中&#xff0c;使用体验流畅。Vue Devtools 由…

【复现】用友U8 oa协同工作系统 文件上传漏洞_57

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 用友U8 &#xff0d;OA 协同办公管理系统&#xff0c;可把日常业务、事物、协作等信息在企业的各分子公司、部门、群组、个人之间…

Nginx网络服务四-----日志、Nginx压缩和ssl

1.自定义访问日志 如果访问出错---404&#xff0c;可以去看error.log日志信息 访问日志是记录客户端即用户的具体请求内容信息&#xff0c;而在全局配置模块中的error_log是记录nginx服务器运行时的日志保存路径和记录日志的level&#xff0c;因此两者是不同的&#xff0c;而且…

Linux——简单的Shell程序

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、Shell程序思路二、Shell代码展示 一、Shell程序思路 用下图的时间轴来表示事件的发生次序…

广联达Linkworks GetAllData 信息泄露漏洞复现

0x01 产品简介 广联达 LinkWorks(也称为 GlinkLink 或 GTP-LinkWorks)是广联达公司(Glodon)开发的一种BIM(建筑信息模型)协同平台。广联达是中国领先的数字建造技术提供商之一,专注于为建筑、工程和建筑设计行业提供数字化解决方案。 0x02 漏洞概述 广联达-Linkworks…

QT常用类

五、常用类 QString 字符串类&#xff08;掌握&#xff09; QString是Qt的字符串类&#xff0c;与C的std::string相比&#xff0c; 不再使用ASCII编码。QString使用的是Unicode编码。 QString中每个字符都是一个16位的QChar&#xff0c;而不是8位的char。 QString完全支持中文&…

2、Web攻防-SQL注入-联合查询注入

用途&#xff1a;个人学习笔记&#xff0c;有所借鉴&#xff0c;欢迎指正&#xff01; 声明&#xff1a;只用于学习交流&#xff0c;点到为止&#xff0c;请勿非法测试。 概念&#xff1a; 联合查询注入&#xff1a;联合注入是回显注入的一种&#xff0c;也就是说联合注入的前…

解决docker中运行的jar包连不上数据库

目录 数据库主机地址设置问题&#xff1a; 网络连接问题&#xff1a; 数据库端口映射&#xff1a; 数据库认证问题&#xff1a; 数据库服务是否正常运行&#xff1a; 日志查看&#xff1a; 如果在 Docker 中运行的 JAR 包无法连接到数据库&#xff0c;有几个可能的原因和…

「JavaSE」String类3:字符串常量池

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;快来卷Java啦 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 字符串常量池 &#x1f349;常量池&#x1f349;字符串常量池&#x1f349;intern 方法 &#x1f349;常量池 在Java程序中&…

Docker 第十九章 : 阿里云个人镜像仓使用

Docker 第十九章 : 阿里云个人镜像仓使用 本章知识点: 如何创建镜像库,如何设置密码,如何登录与退出个人镜像仓,如何本地打镜像,如何将本地镜像推送到个人镜像库。 背景 在项目YapiDocker部署中,因读取mongo:latest 版本不一致,导致后续执行步骤的异常。遇到此场景…