深入学习Synchronized各种使用方法

文章目录

  • 前言
  • 一、synchronized关键字通用在下面四个地方:
    • 1.1synchronized修饰实例方法
    • 1.2synchronized修饰静态方法:
    • 1.3synchronized修饰实例方法的代码块
    • 1.4synchronized修饰静态方法的代码块
    • 2.读入数据
  • 二.Sychronized关键特性
    • 2.1互斥
    • 2.2 刷新内存
    • 2.3可重入
  • 三.同步互斥访问
    • 3.1同步互斥访问
    • 3.2Java中实现同步互斥访问的方法
    • 3.3Java中为什么要提供两种同步器(synchronized 和 Lock)
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:
在Java当中synchronized通常是用来标记一个方法或者代码块。在Java当中被synchronized标记的代码或者方法在同一个时刻只能够有一个线程执行被synchronized修饰的方法或者代码块。因此被synchronized修饰的方法或者代码块不会出现数据竞争的情况,也就是说被synchronized修饰的代码块是并发安全的。


提示:以下是本篇文章正文内容,下面案例可供参考

一、synchronized关键字通用在下面四个地方:

1.1synchronized修饰实例方法

public class SynchronizedExample {// 实例变量private int count = 0;// 同步实例方法public synchronized void increment() {// 在多线程环境中,只有一个线程能够进入这个方法count++;}// 非同步方法public void nonSynchronizedMethod() {// 这个方法没有使用 synchronized 关键字,多个线程可以同时访问}public static void main(String[] args) {SynchronizedExample example = new SynchronizedExample();// 创建多个线程,同时访问同一个实例的 synchronized 方法Thread thread1 = new Thread(() -> {for (int i = 0; i < 5; i++) {example.increment();System.out.println("Thread 1 - Count: " + example.getCount());}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 5; i++) {example.increment();System.out.println("Thread 2 - Count: " + example.getCount());}});// 启动线程thread1.start();thread2.start();}// 获取 count 的方法public int getCount() {return count;}
}

increment 方法使用 synchronized 关键字修饰,确保在同一时间内只有一个线程可以进入该方法,防止多线程并发访问导致数据不一致。
nonSynchronizedMethod 方法没有使用 synchronized 关键字,因此多个线程可以同时访问,可能导致竞态条件(race condition)和数据不一致。
main 方法中创建了两个线程,分别调用 increment 方法来递增 count 变量。
getCount 方法用于获取 count 的值。

1.2synchronized修饰静态方法:

当 synchronized 修饰静态方法时,它锁定的是整个类,而不是实例。这意味着在同一时间内只有一个线程能够访问该静态方法,无论创建了多少个类实例。以下是一个使用 synchronized 修饰静态方法的简单示例:

public class SynchronizedStaticExample {// 静态变量private static int count = 0;// 静态同步方法public static synchronized void increment() {// 在多线程环境中,只有一个线程能够进入这个静态方法count++;}// 非同步方法public void nonSynchronizedMethod() {// 这个方法没有使用 synchronized 关键字,多个线程可以同时访问}public static void main(String[] args) {SynchronizedStaticExample example1 = new SynchronizedStaticExample();SynchronizedStaticExample example2 = new SynchronizedStaticExample();// 创建多个线程,同时访问同一个静态方法Thread thread1 = new Thread(() -> {for (int i = 0; i < 5; i++) {example1.increment();System.out.println("Thread 1 - Count: " + example1.getCount());}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 5; i++) {example2.increment();System.out.println("Thread 2 - Count: " + example2.getCount());}});// 启动线程thread1.start();thread2.start();}// 获取 count 的方法public int getCount() {return count;}
}

increment 方法使用 synchronized 关键字修饰,确保在同一时间内只有一个线程可以进入该静态方法。
nonSynchronizedMethod 方法没有使用 synchronized 关键字,因此多个线程可以同时访问,可能导致竞态条件(race condition)和数据不一致。
main 方法中创建了两个类实例,但由于 increment 方法是静态的,它们共享同一个静态方法,因此在同一时间内只有一个线程能够访问。
getCount 方法用于获取静态变量 count 的值。

1.3synchronized修饰实例方法的代码块

当 synchronized 修饰实例方法时,它锁定的是对象实例,确保在同一时间内只有一个线程能够访问该方法。如果有多个实例,每个实例都有独立的锁。以下是一个使用 synchronized 修饰实例方法的简单示例:

public class SynchronizedInstanceExample {// 实例变量private int count = 0;// 同步实例方法public synchronized void increment() {// 在多线程环境中,只有持有当前对象实例锁的线程能够进入这个方法count++;}// 非同步方法public void nonSynchronizedMethod() {// 这个方法没有使用 synchronized 关键字,多个线程可以同时访问}public static void main(String[] args) {SynchronizedInstanceExample example1 = new SynchronizedInstanceExample();SynchronizedInstanceExample example2 = new SynchronizedInstanceExample();// 创建多个线程,同时访问同一个实例方法Thread thread1 = new Thread(() -> {for (int i = 0; i < 5; i++) {example1.increment();System.out.println("Thread 1 - Count: " + example1.getCount());}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 5; i++) {example2.increment();System.out.println("Thread 2 - Count: " + example2.getCount());}});// 启动线程thread1.start();thread2.start();}// 获取 count 的方法public int getCount() {return count;}
}

increment 方法使用 synchronized 关键字修饰,确保在同一时间内只有持有当前对象实例锁的线程能够进入该方法。
nonSynchronizedMethod 方法没有使用 synchronized 关键字,因此多个线程可以同时访问,可能导致竞态条件(race condition)和数据不一致。
main 方法中创建了两个类实例,每个实例都有独立的锁,因此它们的 increment 方法互不影响。
getCount 方法用于获取实例变量 count 的值

1.4synchronized修饰静态方法的代码块

当 synchronized 修饰静态方法时,它锁定的是类的 Class 对象,确保在同一时间内只有一个线程能够访问该静态方法。以下是一个使用 synchronized 修饰静态方法的简单示例

public class SynchronizedStaticExample {// 静态变量private static int count = 0;// 静态同步方法public static synchronized void increment() {// 在多线程环境中,只有一个线程能够进入这个静态方法count++;}// 非同步方法public void nonSynchronizedMethod() {// 这个方法没有使用 synchronized 关键字,多个线程可以同时访问}public static void main(String[] args) {SynchronizedStaticExample example1 = new SynchronizedStaticExample();SynchronizedStaticExample example2 = new SynchronizedStaticExample();// 创建多个线程,同时访问同一个静态方法Thread thread1 = new Thread(() -> {for (int i = 0; i < 5; i++) {SynchronizedStaticExample.increment();System.out.println("Thread 1 - Count: " + SynchronizedStaticExample.getCount());}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 5; i++) {SynchronizedStaticExample.increment();System.out.println("Thread 2 - Count: " + SynchronizedStaticExample.getCount());}});// 启动线程thread1.start();thread2.start();}// 获取 count 的方法public static int getCount() {return count;}
}

increment 方法使用 synchronized 关键字修饰,确保在同一时间内只有一个线程能够进入该静态方法。
nonSynchronizedMethod 方法没有使用 synchronized 关键字,因此多个线程可以同时访问,可能导致竞态条件(race condition)和数据不一致。
main 方法中创建了两个类实例,但由于 increment 方法是静态的,它们共享同一个静态方法,因此在同一时间内只有一个线程能够访问。
getCount 方法用于获取静态变量 count 的值。

2.读入数据

代码如下(示例):

data = pd.read_csv('https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())

该处使用的url网络请求的数据。


二.Sychronized关键特性

2.1互斥

synchronized 会起到互斥效果, 某个线程执行到某个对象的 synchronized 中时, 其他线程如果也执行到同一个对象 synchronized 就会阻塞等待.
进入 synchronized 修饰的代码块, 相当于 加锁
退出 synchronized 修饰的代码块, 相当于 解锁

2.2 刷新内存

synchronized 的工作过程:

  1. 获得互斥锁
  2. 从主内存拷贝变量的最新副本到工作的内存
  3. 执行代码
  4. 将更改后的共享变量的值刷新到主内存
  5. 释放互斥锁

2.3可重入

看到的这个例子很形象
在 Java 中,synchronized 关键字具有可重入性,这意味着如果一个线程已经获得了某个对象的锁,那么它可以再次请求该对象的锁而不会被阻塞。可重入性使得同一个线程在执行一个方法(或代码块)时可以再次进入同步锁定的代码区域,而不会被自己已经持有的锁所阻塞。

这种机制是为了防止由于递归调用或者方法内部调用其他同步方法而导致的死锁。如果不支持可重入性,那么在同一线程中多次调用同步方法,就会因为持有同一个锁而产生死锁。
在这里插入图片描述

public class ReentrantExample {public static void main(String[] args) {ReentrantExample example = new ReentrantExample();example.outerMethod();}public synchronized void outerMethod() {System.out.println("Outer Method");innerMethod();}public synchronized void innerMethod() {System.out.println("Inner Method");}
}

三.同步互斥访问

3.1同步互斥访问

在多线程编程中,通常会有多个线程同时访问一个资源的情况,同步互斥访问就是在同一时间只能有一个线程对同一资源进行访问。

3.2Java中实现同步互斥访问的方法

同步互斥访问的解决办法是设计一个同步器,对多个线程同时访问同一个共享、可变资源的情况,这个资源我们称之其为临界资源;这种资源可能是: 对象、变量、文件等
同步器采用的方案都是序列化访问临界资源。即在同一时刻,只能有一个线程访问临 界资源。
共享:资源可以由多个线程同时访问。
可变:资源可以在其生命周期内被修改。
Java中目前有 synchronized 和 Lock (ReentrantLock)。

3.3Java中为什么要提供两种同步器(synchronized 和 Lock)

synchronized在1.5版本时的状况:这是因为在jdk1.5版本的时候,jdk官方就提供出了 synchronized 锁,但是在1.5版本的时候,synchronized 锁的加锁方式只有一个,就是通过内部对象Monitor(监视器锁)实现,基于进入与退出Monitor对象实现方法与代码块同步,监视器锁的实现依赖底层操作系统的Mutex lock(互斥锁)实现,它是一个重量级锁性能较低,也就是比较消耗性能。
Lock锁的出现:由于 synchronized 锁的性能不大好,加的锁都是重要级别的锁,涉及到线程之间的状态切换,要从用户态切换到内核态,所以就有一个人设计了Lock锁,在当时,Lock锁的性能要比 synchronized 好很多。
synchronized锁的优化:后来jdk官方就对synchronized锁进行了优化,成了现在这个样子,我感觉真的基本和Lock差不多了。

总结

好了,今天的blog就到此为止,期待大佬们的三连和评论

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

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

相关文章

CentOS 7 虚拟机java项目部署tomcat

首先安装java环境 下载安装包:jdk-19_linux-x64_bin.tar.gz_免费高速下载|百度网盘-分享无限制 (baidu.com) 将安装包上传到虚拟机 解压 tar zxvf jdk-19_linux-x64_bin.tar.gz 移动文件到 mv jdk-19.0.1 /usr/jdk-19.0.1 编辑配置文件 vim /etc/profile export JAVA…

解决cad找不到msvcr100.dll的有效方法,完美修复dll问题

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是由于找不到msvcr100.dll文件而导致CAD软件无法正常运行的情况&#xff0c;系统无法找到所需的动态链接库文件。但是通过一些简单的解决方法&#xff0c;我们可以快速解决这个问题并继续我们的…

【动态规划】LeetCode-62.不同路径

&#x1f388;算法那些事专栏说明&#xff1a;这是一个记录刷题日常的专栏&#xff0c;每个文章标题前都会写明这道题使用的算法。专栏每日计划至少更新1道题目&#xff0c;在这立下Flag&#x1f6a9; &#x1f3e0;个人主页&#xff1a;Jammingpro &#x1f4d5;专栏链接&…

HNU-计算机网络-讨论课2

第二次 有关网络智能、安全以及未来网络的讨论 一、必选问题&#xff08;每组自由选择N个&#xff0c;保证组内每人负责1个&#xff09; 网络的发展促进信息的传播&#xff0c;极大提高了人类的感知能力&#xff0c;整个世界都被纳入人类的感知范围。但人们对信息系统以及数据…

手持式安卓主板_PDA安卓板_智能手持终端方案

手持式安卓主板方案是一种智能终端设备&#xff0c;具备自动对焦和闪光灯功能&#xff0c;可以在昏暗的环境下快速扫描二维码并轻松采集数据。该方案还提供多渠道支付和数据采集功能&#xff0c;为用户提供了便捷的体验。 该方案的产品基于手持式安卓主板&#xff0c;并搭载了八…

C/C++,图算法——求强联通的Tarjan算法之源程序

1 文本格式 #include <bits/stdc.h> using namespace std; const int maxn 1e4 5; const int maxk 5005; int n, k; int id[maxn][5]; char s[maxn][5][5], ans[maxk]; bool vis[maxn]; struct Edge { int v, nxt; } e[maxn * 100]; int head[maxn], tot 1; vo…

Unity UGUI控件之Horizontal Layout Group

Horizontal Layout Group是Unity中的UGUI控件&#xff0c;用于在水平方向上对子对象进行布局。 主要有一下作用&#xff1a; 水平布局&#xff1a;Horizontal Layout Group将子对象按照水平方向进行布局&#xff0c;可以控制子对象的排列顺序和间距。自动调整尺寸&#xff1a…

不到1000行代码,PyTorch团队让Llama 7B提速10倍

在过去的一年里&#xff0c;生成式 AI 发展迅猛&#xff0c;在这当中&#xff0c;文本生成一直是一个特别受欢迎的领域&#xff0c;很多开源项目如 llama.cpp、vLLM 、 MLC-LLM 等&#xff0c;为了取得更好的效果&#xff0c;都在进行不停的优化。 作为机器学习社区中最受欢迎框…

面试就是这么简单,offer拿到手软(四)—— 常见java152道基础面试题

面试就是这么简单&#xff0c;offer拿到手软&#xff08;一&#xff09;—— 常见非技术问题回答思路 面试就是这么简单&#xff0c;offer拿到手软&#xff08;二&#xff09;—— 常见65道非技术面试问题 面试就是这么简单&#xff0c;offer拿到手软&#xff08;三&#xff…

WIN10下解决HIVE 初始化MYSQL表报错:Unknown version specified for initialization

今天本地WINDOWS装HIVE&#xff0c;走到最后一步初始化数据库死活不通过&#xff1a; D:\hive\hive-rel-release-3.1.3\bin\ext>hive --service schematool -dbType mysql -initSchema --verbose SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found bind…

flask 上传文件

from flask import Flask, request, render_template,redirect, url_for from werkzeug.utils import secure_filename import os from flask import send_from_directory # send_from_directory可以从目录加载文件app Flask(__name__)#UPLOAD_FOLDER media # 注意&#xff…

会声会影2024购买多少钱 会声会影在哪里购买

掌握视频编辑技术&#xff0c;能为我们的工作和生活带来很多帮助。例如&#xff1a;将我们精心编辑的视频&#xff0c;上传到抖音、快手等平台进行变现&#xff1b;通过天马行空的视频创意&#xff0c;摇身一变成为B站up主。因此&#xff0c;拥有一款像会声会影这样的视频编辑软…

信号可靠性剖析

问题 基于信号发送的进程间通信方式可靠吗&#xff1f;&#xff1f;&#xff1f; 信号查看(kill -l) 信号的分类 不可靠信号 (传统信号) 信号值在 [1, 31] 之间的所有信号 可靠信号 (实时信号) 信号值在 [SIGRTMIN&#xff0c;SIGRTMAX]&#xff0c;即&#xff1a;[34&…

计算机组成原理学习-总线总结

复习本章时&#xff0c;思考以下问题&#xff1a; 1)引入总线结构有什么好处&#xff1f;2)引入总线结构会导致什么问题&#xff1f;如何解决&#xff1f;

变电站设计综合应用软件

产品概述 变电站设计综合应用软件,以下称为软件,是一款面向智能变电站虚拟二次回路设计和光纤回路设计的单机版桌面应用软件。软件为用户提供了直观易用、一键安装、功能齐全的轻量级的设计支撑。像常规的工具化软件一样,该软件在开始设计时需要通过新建一个项目,开启一段…

【C++】const关键字的详解!!

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

Android MVVM+coroutine+retrofit+flow+hilt

文章目录 Android MVVMcoroutineretrofitflowhilt概述依赖注入层数据层视图层模型视图层代码下载 Android MVVMcoroutineretrofitflowhilt 概述 代码结构&#xff1a; 依赖注入层 数据库&#xff1a; Module InstallIn(SingletonComponent::class) class DBModule {Singleto…

数据结构与算法-D2D3线性表之顺序表

线性表&#xff1a;包含若干数据元素的一个线性序列&#xff0c;特征如下&#xff1a; 1&#xff09;对非空表&#xff0c;a0是表头&#xff0c;无前驱&#xff1b; 2&#xff09;an-1是表尾&#xff0c;无后继&#xff1b; 3&#xff09;其他元素仅且仅有一个前驱&#xff0c;…

基于YOLOv8深度学习的120种犬类检测与识别系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战、狗类检测、犬种识别

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

【“C++ 精妙之道:解锁模板奇谭与STL精粹之门“】

【本节目标】 1. 泛型编程 2. 函数模板 3. 类模板 4. 什么是STL 5. STL的版本 6. STL的六大组件 7. STL的重要性 8. 如何学习STL 9.STL的缺陷 1. 泛型编程 如何实现一个通用的交换函数呢&#xff1f; void Swap(int& left, int& right) {int temp left;lef…