深入学习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 的工作过程:
- 获得互斥锁
- 从主内存拷贝变量的最新副本到工作的内存
- 执行代码
- 将更改后的共享变量的值刷新到主内存
- 释放互斥锁
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就到此为止,期待大佬们的三连和评论
相关文章:
深入学习Synchronized各种使用方法
文章目录 前言一、synchronized关键字通用在下面四个地方:1.1synchronized修饰实例方法1.2synchronized修饰静态方法:1.3synchronized修饰实例方法的代码块1.4synchronized修饰静态方法的代码块2.读入数据 二.Sychronized关键特性2.1互斥2.2 刷新内存2.3…...
【idea】设置鼠标滚轮控制缩放大小
1、点击file 选择Setting 2、点击Editor 下面的 General 3、勾选 Mouse Control 下面的 Change font size with CtrlMouse Wheel in 4、点级apply 5、按 ctrl键 鼠标滚轮缩放字体的大小...
合并两个有序数组(leetcode_刷题1)
目录 题目:合并两个有序数组 题目分析方向1: 题目分析方向2: 题目:合并两个有序数组 题目要求: 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums…...
麒麟linux将图片批量生成PDF的方法
笔者手里有一批国产linu系统,目前开始用在日常的工作生产环境中,我这个老程序猿勉为其难的充当运维的或网管的角色。 国产linux系统常见的为麒麟Linux,统信UOS等,基本都是基于debian再开发的linux。 问题描述: wind…...
Linux——vim编辑文件时——.swp文件解决方案
test.cpp样例 当我们vim test.cpp进入编辑文件。 却忘记了保存退出 再次进入就会出现一下画面 当你摁下Enter键位 出现以下几个选项 O——是只读不写 E——是正常打开文件但不会载入磁盘内容 R——覆盖——是加载存储磁盘的文件(当我们忘记保存时,系统会自动帮我…...
【Maven】清理 maven 仓库
初始情况下,我们的本地仓库是没有任何jar包的,此时会从私服去下载(如果没有配置,就直接从中央仓库去下载)。 可能由于网络的原因,jar包下载不完全,这些不完整的jar包都是以lastUpdated结尾。此…...
APOLLO自动驾驶技术沙龙:未来已来,共创智能交通新时代
在这次Apollo会议上,我深刻地感受到了人工智能自动驾驶技术领域的最新进展和未来趋势。作为一名从事软件开发工作的人员,我深感荣幸能够参加这次盛会。 前言 本次活动是百度Apollo社区工程师齐聚首钢Park,带来现场实操与技术分享。主要围绕Ap…...
Java面试题12
1.redis 怎么实现分布式锁? Redis可以通过以下方式实现分布式锁: 使用RedLock算法:多个Redis节点组合使用,通过竞争锁来达到分布式锁的效果。使用SETNX命令:利用SETNX(SET if Not eXists)命令…...
ubuntu上创建服务启动python脚本
场景 最近在使用ubuntu服务器部署MySQL和同步数据,同步数据使用的是python,但是我不能直接操作服务器,只能通过Xshell远程访问服务器,但是启动python脚本的时候如果关掉xshell会停止Python脚本,所以如果要让python脚本…...
51单片机制作数字频率计
文章目录 简介设计思路工作原理Proteus软件仿真软件程序实验现象测量误差和范围总结 简介 数字频率计是能实现对周期性变化信号频率测量的仪器。传统的频率计通常是用很多的逻辑电路和时序电路来实现的,这种电路一般运行较慢,而且测量频率的范围较小。这…...
java中强引用、软引用、弱引用、虚引用的区别是什么?
Java中的引用类型主要分为强引用、软引用、弱引用和虚引用,它们之间的区别主要体现在垃圾回收的行为上。 强引用(Strong Reference):这是使用最普遍和默认的引用类型。如果一个对象具有强引用,那么垃圾回收器就永远不会…...
springboot -事务管理
事务 概念 事务是一组操作的集合,它是一个不可分割的工作单位,这些操作要么同时成功,要么同时失败。 操作 开启事务: start transaction / begin提交事务:commit回滚事务: rollback 注解 Transactional …...
商城系统通过Kafka消息队列,实现订单的处理和状态更新
以下是一个简单的Spring Boot应用程序示例,演示如何使用Kafka实现订单的处理和状态更新。 首先,我们创建一个名为“order”的topic,在application.yaml配置文件中添加Kafka的配置: spring:kafka:bootstrap-servers: localhost:9…...
IntelRealSense深度相机D455在ROS1运行中的消息内容
IntelRealSense深度相机D455在ROS1运行中的消息内容 通过下面命令所有相关信息通过ros topic的方式发布出去rosnode查看rqt_graph查看rostopic查看通过下面命令直接查看RVIZ中点云信息rosnode查看rqt_graph查看rostopic查看 Physical Port:: /sys/devices/pci0000:0…...
公有云迁移研究——AWS Translate
大纲 1 什么是Translate2 Aws Translate是怎么运作的3 Aws Translate和Google Translate的区别4 迁移任务4.1 迁移原因 5 Aws Translate的Go demo6 迁移中遇到的问题6.1 账号和权限问题:6.2 小语种 1 什么是Translate Translate是一种文本翻译服务,它使…...
【laBVIEW学习】4.声音播放,自定义图标,滚动条设置,保存参数以及恢复参数
一。声音播放(报错,未实现) 1.报错4810 2.解决方法: 暂时未解决。 二。图片修改 1.目标:灯泡---》自定义灯泡 2.步骤: 1.右键点击--》自定义运行 表示可以制作自定义类型 2.右键--》打开自定义类型 这样就…...
《论文阅读》使用条件变分自动编码器学习神经对话模型的语篇水平多样性 2017 ACL
《论文阅读》使用条件变分自动编码器学习神经对话模型的语篇水平多样性 2017 ACL 前言简介相关知识Stochastic Gradient Variational BayesMultivariate Gaussian DistributionIsotropic Gaussian DistributionReparameterization Trickprior network & posterior network …...
【win32_003】不同字符集下的通用字符串语法TCHAR、TEXT、PTSTR、PCTSTR
TCHAR 通用 根据项目属性是否使用Unicode字符集,TCHAR被解释为CHAR(char)或WCHAR(wchar_t)数据类型。 TCHAR a ‘A’ ; TCHAR arr [] TEXT(“AA”); TCHAR arr [100] TEXT(“AA”); TCHAR *pstr TEXT(“AA”); TEXT宏 #ifdef UNICODE #define __TEXT(quote) L#…...
《漫长的等待》—— 读后感
前几天下班地铁上,人太多,看技术书籍看不进去,翻阅微信读书,看到了这本书,看了几章免费的章节,因为后续需要买会员就没有继续读,但是这几天偶尔还是会想到书籍中的情节,所以今天充了…...
基于ROPNet项目训练modelnet40数据集进行3d点云的配置
项目地址: https://github.com/zhulf0804/ROPNet 在 MVP Registration Challenge (ICCV Workshop 2021)(ICCV Workshop 2021)中获得了第二名。项目可以在win10环境下运行。 论文地址: https://arxiv.org/abs/2107.02583 网络简介…...
力扣215. 数组中的第K个最大元素
堆排序 前言 面试中著名的 TopK 排序;常见的解法有冒泡排序、堆排序;更深入的思路可以参考:拜托,面试别再问我TopK了!!!使用了堆排序的算法,关于堆可以参考:堆数据结构的…...
轻量封装WebGPU渲染系统示例<40>- 多层材质的Mask混合(源码)
当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/MaskTextureEffect.ts 当前示例运行效果: 两层材质效果: 三层材质效果: 此示例基于此渲染系统实现,当前示例TypeScript源码如下: export c…...
程序员的实用网站导航与推荐
当你遇到问题时 Stack Overflow:订阅他们的每周新闻和任何你感兴趣的主题Google:全球最大搜索引擎必应:在你无法使用Google的时候CSDN:聊胜于无AI导航一号AI导航二号 新闻篇 OSCHINA:中文开源技术交流社区 针对初学…...
上午面了个腾讯拿 38K 出来的,让我见识到了基础的天花板
今年的校招基本已经进入大规模的开奖季了,很多小伙伴收获不错,拿到了心仪的 offer。 各大论坛和社区里也看见不少小伙伴慷慨地分享了常见的面试题和八股文,为此咱这里也统一做一次大整理和大归类,这也算是划重点了。 俗话说得好…...
【halcon】C# halcon 内存暴增
1 读取图片需要及时手动释放 一个6M的图片通过halcon进行加载,大约会消耗200M的内存,如果等待GC回收,而你又在不停的读取图片,你的内存占用,将在短时间内飙升。 2 halcon控件显示图片需要清空。 /// <summary>…...
LeetCode130. Surrounded Regions
文章目录 一、题目二、题解 一、题目 Given an m x n matrix board containing ‘X’ and ‘O’, capture all regions that are 4-directionally surrounded by ‘X’. A region is captured by flipping all O’s into X’s in that surrounded region. Example 1: Input…...
【实战教程】PHP如何轻松对接腾讯云COS,实现文件上传下载?
腾讯云提供了一系列丰富的云服务,其中包括对象存储(Cloud Object Storage,简称COS),它是一种高可靠性、可扩展性强的云存储服务。本文将介绍如何使用PHP对接腾讯云COS存储服务,实现文件的上传和下载功能。 …...
pytorch学习10-网络模型的保存和加载
系列文章目录 pytorch学习1-数据加载以及Tensorboard可视化工具pytorch学习2-Transforms主要方法使用pytorch学习3-torchvisin和Dataloader的使用pytorch学习4-简易卷积实现pytorch学习5-最大池化层的使用pytorch学习6-非线性变换(ReLU和sigmoid)pytorc…...
SQL Server 2016(分离和附加数据库)
1、实验环境。 基于上一个实验《SQL Server(创建数据库)》 2、需求描述。 class数据库的数据文件和事务日志文件都位于C:\db_class目录下。现在需要把class数据库的数据文件和事务日志文件分开存放,数据文件class.mdf存放于原位置࿰…...
用友U8 Cloud RegisterServlet SQL注入漏洞复现
0x01 产品简介 用友U8 Cloud是用友推出的新一代云ERP,主要聚焦成长型、创新型企业,提供企业级云ERP整体解决方案。 0x02 漏洞概述 用友U8 Cloud RegisterServlet接口处存在SQL注入漏洞,未授权的攻击者可通过此漏洞获取数据库权限,从而盗取用户数据,造成用户信息泄露。 …...
python做动态网站/加盟培训机构
引用 C中有一个很方便的语法叫做引用,作用就是使得函数能够对传入的参数作出全局有效的改动。用法很简单,就是在传入参数的类型后面加上&就可以指明传入的参数是引用。 例子: #include <stdio.h>void change(int& x){x 1; } i…...
引航博景网站做的很好吗/java培训机构十强
main.sh 主控制脚本#!/bin/bash# 是否发送邮件的开关(维护模式下我们需要关闭此功能,监控还是继续,但不发任何邮件。)export send1# 过滤ip地址(一旦报警,需要需要知道是哪台机器的IP,没有服务端,全部都是独立运行的。…...
用卡通人物做网站属于侵权吗/百度提交网址多久才会收录
满意答案nico402013.08.18采纳率:53% 等级:12已帮助:6620人200分是一个诱惑!-------------------------------------------------------你的问题描述有问题。回答者“tbsoo_com ”的计算这里$i-1是错误的,应该加上括…...
网站管理系统源码/关键词排名查询官网
把 Windows 下的应用部署到 Linux 下,使用到了 Quartz 集群的特性,所以建了 MySql 的中间表,一启动看到报错: Invocation of init method failed; nested exception is org.quartz.JobPersistenceException: Couldnt retrieve tri…...
久久营销网站/北京网站seo
English中文含义Terrain地形,Spur山嘴;尖坡Depression洼地Valley峡谷Saddle鞍部Hill小山Draw山坳Cliff悬崖Ridge山脊Protractor量角器contour line等高线legend图例azimuth方位角relief地形MGRS (Military Grid Reference System)军事格网坐标universal …...
大连金州代做网站公众号/快速排名教程
马哲包括5大部分即唯物论,辩证法,认识论,历史唯物论,资本主义本质论。 其中辩证法又包括: 1.两大特征:(1)普遍联系(2)永恒发展。 2.三大规律:&…...