Synchronized 关键字
在Java中,线程同步使用最多的方法是使用synchronized关键字。每个Java对象都隐含有一把锁,这里称为Java内置锁(或者对象锁、隐式锁)。使用synchronized(syncObject)调用相当于获取 syncObject 的内置锁,所以可以使用内置锁对临界区代码段进行排他性保护。
synchronized 同步方法
synchronized 关键字是Java的保留字,当使用synchronized关键字修饰一个方法的时候,该方法被声明为同步方法,具体的例子如下:
//同步方法
public synchronized void selfplus(){amount++;
}
关键字synchronized的位置处于同步方法的返回类型之前。回到前面的线程安全小实验,现在使用synchronized关键字对临界区代码段进行保护,代码如下:
package com.crazymakercircle.plus;// 省略importpublic class SafePlus{private Integer amount -0://临界区代码段使用synchronized进行保护 public synchronized void selfplus () {amount++;}
}
再次运行测试用例程序,累加10000次之后,最终的结果不再有偏差,与预期的结果(10000)是相同的。
在方法声明中设置synchronized同步关键字,保证其方法的代码执行流程是排他性的。任何时间只允许一个线程进入同步方法(临界区代码段),如果其他线程需要执行同一个方法,那么只能等待和排队。
synchronized 同步块
对于小的临界区,我们直接在方法声明中设置synchronized同步关键字,可以避免竞态条件的问题。但是对于较大的临界区代码段,为了执行效率,最好将同步方法分为小的临界区代码段。通过下面这个例子来具体讲述:
public class TwoPlus { private int sum1 = 0; private int sum2 =0;//同步方法public synchronized void plus(int vall,int val2){//临界区代码段this.sum1 += vall; this.sum2 += va12;}
}
在以上代码中,临界区代码段包含对两个临界区资源的操作,这两个临界区资源分别为sum1和 sum2。使用synchronized对plus(int vall, int val2)进行同步保护之后,进入临界区代码段的线程拥有sum1和sum2的操作权,并且是全部占用。一旦线程进入,当线程在操作sum1而没有操作sum2时,也将sum2的操作权白白占用,其他的线程由于没有进入临界区,只能看着sum2被闲置而不能去执行操作。
所以,将synchronized加在方法上,如果其保护的临界区代码段包含的临界区资源(要求是相互独立的)多于一个,就会造成临界区资源的闲置等待,进而会影响临界区代码段的吞吐量、为了提升吞吐量,可以将synchronized关键字放在函数体内,同步一个代码块。synchronized 同步块的写法是:
synchronized (syncObject) //同步块而不是方法
{//临界区代码段的代码块
}
在synchronized同步块后边的括号中是一个syncObject对象,代表着进入临界区代码段需要获取 syncObject对象的监视锁,或者说将syncObject对象监视锁作为临界区代码段的同步锁。由于每一个Java对象都有一把监视锁,因此任何Java对象都能作为synchronized的同步锁。
单个线程在synchronized同步块后面的同步锁后,才能进入临界区代码段;反过来说,当一个线程获得syncObject对象的监视锁后,其他线程就只能等待。
使用synchronized同步块对上面的TwoPlus类进行吞吐量的提升改造,具体的代码如下:
public class TwoPlus {private int suml0; private int sum2 =0;private Integer sumllock - new Integer(1); //同步锁一 private Integer sum2Lock = new Integer(2); //同步锁二 public void plus(int val1, int val2){//同步块1synchronized (this.sumlLock){this.sum1 += vall;}//同步块2synchronized(this.sum2Lock){this.sum2 += val2;}}
}
改造之后,对两个独立的临界区资源sum1 和sum2的加法操作可以并发执行了,在某一个时刻,不同的线程可以对sum1和sum2同时进行加法操作,提升了plus(方法的吞吐量。
在TwoPlus代码中,由于同步块1和同步块2保护着两个独立的临界区代码段,需要两把不同的 syncObject对象锁,因此TwoPlus代码新加了sum1Lock和sum2Lock两个新的成员属性。这两个属性没有参与业务处理,TwoPlus仅仅利用了sum1Lock 和 sum2Lock的内置锁功能。
synchronized 方法和synchronized同步块有什么区别呢?总体来说,synchronized方法是一种粗粒度的并发控制,某一时刻只能有一个线程执行该synchronized方法;而synchronized代码块是一种细粒度的并发控制,处于synchronized块之外的其他代码是可以被多个线程并发访问的。在一个方法中,并不一定所有代码都是临界区代码段,可能只有几行代码会涉及线程同步问题。所以synchronized 代码块比synchronized方法更加细粒度地控制了多个线程的同步访问。 synchronized 方法和synchronized代码块有什么联系呢?在Java的内部实现上,synchronized方法实际上等同于用一个synchronized代码块,这个代码块包含同步方法中的所有语句,然后在 synchronized 代码块的括号中传入this关键字,使用this对象锁作为进入临界区的同步锁。
例如,下面两种实现多线程同步的plus方法版本编译成JVM内部字码后结果是一样的。版本一,使用synchronized代码块对方法内部全部代码进行保护,具体代码如下:
public void plus () {synchronized(this) { //对方法内部全部代码进行保护amount++;}
}
版本二,使用synchronized方法对方法内部全部代码进行保护,具体代码如下:
public synchronized void plus() {amount++;
}
综上所述,synchronized方法的同步锁实质上使用了this对象锁,这样就免去了手工设置同步锁的工作。而使用synchronized代码块需要手工设置同步锁。
静态的同步方法
在Java世界里一切皆对象。Java有两种对象:Object实例对象和Class对象。每个类运行时的类型信息用Class对象表示,它包含与类名称、继承关系、字段、方法有关的信息。JVM将一个类加载入自己的方法区内存时,会为其创建一个Class对象,对于一个类来说其Class对象是唯一的。 Class类没有公共的构造方法,Class对象是在类加载的时候由Java虚拟机调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。
所有的类都是在第一次使用时被动态加载到JVM中的(懒加载),其各个类都是在必需时才加载的。这一点与许多传统语言(如C++)都不同,JVM为动态加载机制配套了一个判定一个类是否已经被加载的检查动作,使得类加载器首先检查这个类的Class对象是否已加载。如果尚未加载,类加载器就会根据类的全限定名查找.class文件,验证后加载到JVM的方法区内存并构造其对应的Class对象。
普通的synchronized实例方法,其同步锁是当前对象this的监视锁。如果某个synchronized方法是static(静态)方法,而不是普通的对象实例方法,其同步锁又是什么呢?
下面展示一个使用synchronized关键字修饰static方法的例子,具体如下:
package com.crazymakercircle.plusi
//省略import
public class SafeStaticMethodPlus{ //静态的临界区资源private static Integer amount = 0;//使用synchronized关键字修饰 static方法public static synchronized void selfPlus (){amount++;}
}
大家都知道,静态方法属于Class实例而不是单个Object实例,在静态方法内部是不可以访
问Object实例的this引用(也叫指针、句柄)的。所以,修饰static方法的synchronized关键字就没有办法获得Object 实例的this对象的监视锁。
实际上,使用synchronized关键字修饰static方法时,synchronized的同步锁并不是普通Object 对象的监视锁,而是类所对应的 Class 对象的监视锁。
为了以示区分,这里将Object对象的监视锁叫作对象锁,将Class对象的监视锁叫作类锁。当synchronized 关键字修饰static方法时,同步锁为类锁:当synchronized关键字修饰普通的成员方法(非静态方法)时,同步锁为类锁。由于类的对象实例可以有很多,但是每个类只有一个Class实例,因此使用类锁作为synchronized的同步锁时会造成同一个JVM内的所有线程只能互斥地进入临界区段。
//对JVM内的所有线程同步
public static synchronized void selfplus (){//临界区代码
}
所以,使用synchronized关键字修饰static方法是非常粗粒度的同步机制。
通过synchronized关键字所抢占的同步锁什么时候释放呢?一种场景是synchronized块(代码块或者方法)正确执行完毕,监视锁自动释放;另一种场景是程序出现异常,非正常退出 synchronized块,监视锁也会自动释放。所以,使用synchronized块时不必担心监视锁的释放问题。
相关文章:
Synchronized 关键字
在Java中,线程同步使用最多的方法是使用synchronized关键字。每个Java对象都隐含有一把锁,这里称为Java内置锁(或者对象锁、隐式锁)。使用synchronized(syncObject)调用相当于获取 syncObject 的内置锁,所以可以使用内置锁对临界区代码段进行…...
Maven系列第8篇:大型Maven项目,快速按需任意构建
本篇涉及到的内容属于神技能,多数使用maven的人都经常想要的一种功能,但是大多数人都不知道如何使用,废话不多说,上干货。 需求背景 我们需要做一个电商项目,一般都会做成微服务的形式,按业务进行划分&am…...
卷积神经网络(CNN)的组成结构以及其优点
卷积神经网络(Convolutional Neural Network,简称CNN)是一种深度学习模型,主要用于处理具有网格结构的数据,如图像和视频。它的结构包含以下几个关键组件: 卷积层(Convolutional Layerÿ…...
[③ADRV902x]: Digital Filter Configuration(接收端)
前言 本篇博客主要总结了ADRV9029 Rx接收端链路中各个滤波器的配置。配置不同的滤波器系数以及不同的参数,可以对输入的数字信号灵活得做decimation处理,decimation信号抽取,就是降低信号采样率的过程。 Receiver Signal Path 下图为接收端…...
企业安全—DevSecOps概述详情
0x00 前言 SDL存在的问题在于体量过于庞大,不利于快速进行适配和进行,所以就有了DevSecOps,实际上是因为敏捷开发也就是DevOps的推进,并且坐上了云服务模式的火车,所以这一系列的东西都开始普及。DevSecOps作为DevOps…...
数据结构与算法(十):动态规划与贪心算法
参考引用 Hello 算法 Github:hello-algo 1. 动态规划算法 动态规划将一个问题分解为一系列更小的子问题,并通过存储子问题的解来避免重复计算,从而大幅提升时间效率 问题:给定一个共有 n 阶的楼梯,你每步可以上 1 阶或…...
【C++代码】安排行程,N皇后,解数独--代码随想录
题目:重新安排行程 给你一份航线列表 tickets ,其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必…...
SpringCloud Alibaba【二】nacos
nacos配置与使用 nacos初步使用nacos安装与配置创建命名空间 nacos使用与配置创建新项目作为父项目 创建nacos服务端项目pom.xmlapplication.yml启动类 创建nacos客户端项目pom.xml application.yml启动类 启动测试 nacos配置负载均衡改造生产者nacos-provider-projectcontroll…...
C++中的fsanitize指令
一个集成在 gcc、clang 编译器中的编译指令,可以有效测试程序中的一些诸如数组越界、未定义行为等情况。 举个例子: #include <bits/stdc.h> using namespace std;const int maxn2e55,mxr1e5,maxm1e75; int head[maxn],nxt[maxn],to[maxn],f[max…...
【AI视野·今日Robot 机器人论文速览 第五十八期】Thu, 19 Oct 2023
AI视野今日CS.Robotics 机器人学论文速览 Thu, 19 Oct 2023 Totally 25 papers 👉上期速览✈更多精彩请移步主页 Daily Robotics Papers InViG: Benchmarking Interactive Visual Grounding with 500K Human-Robot Interactions Authors Hanbo Zhang, Jie Xu, Yuch…...
Java截取(提取)子字符串(substring()),Java分割字符串(split())
在 String 中提供了两个截取字符串的方法,一个是从指定位置截取到字符串结尾,另一个是截取指定范围的内容。下面对这两种方法分别进行介绍。 1. substring(int beginIndex) 形式 此方式用于提取从索引位置开始至结尾处的字符串部分。调用时,…...
从厨房间到股市:家庭主妇的华美转身
我一直是一个安于现状的家庭主妇。生活中,我热爱烹饪、园艺和照顾家人,但我也渴望能有更多的自我实现和价值感。在机缘巧合下,我接触到了卓扬网,一个专业的股票投资平台。从那刻起,我的人生发生了翻天覆地的变化。 初…...
Oracle 数据库的锁排查方法
关键字 oracle lock 问题描述 Oracle 数据库上锁问题如何排查 解决问题思路 准备数据 create table lock_test(name varchar(10),age varchar(10));insert into lock_test values(ff,10); insert into lock_test values(yy,20); insert into lock_test values(ll,30);Orac…...
混合精度训练原理之float16和float32数据之间的互相转换
混合精度训练原理之float16和float32数据之间的互相转换 本篇文章参考:全网最全-混合精度训练原理 上述文章已经讲解的比较详细,本文只是从数值角度分析: 1. float32转入float16的精度误差 2. 在深度学习的混精度训练当中,当参数…...
网络协议--ICMP:Internet控制报文协议
6.1 引言 ICMP经常被认为是IP层的一个组成部分。它传递差错报文以及其他需要注意的信息。ICMP报文通常被IP层或更高层协议(TCP或UDP)使用。一些ICMP报文把差错报文返回给用户进程。 ICMP报文是在IP数据报内部被传输的,如图6-1所示。 ICMP…...
《红蓝攻防对抗实战》三.内网探测协议出网之HTTP/HTTPS协议探测出网
目录 一. 在 Windows 操作系统中探测 HTTP/HTTPS 出网 1. Bitsadmin 命令 2.Certuil 命令 2.Linux系统探测HTTP/HTTPS出网 1.Curl命令 2.Wget命令 对目标服务器探测 HTTP/HTTPS 是否出网时,要根据目标系统类型执行命令,不同类型的操作系统使用的探…...
【Win11】系统重装教程(最新最详细)
目录 一.简介 二.用U盘制作PE系统 三、安装系统 软件:Windows 11版本:21H2语言:简体中文大小:5.14G安装环境:PE系统,至少7代处理器硬件要求:CPU2.0GHz 内存4G(或更高)下载通道①丨…...
如何构建一个外卖微信小程序
随着外卖行业的不断发展,越来越多的商家开始关注外卖微信小程序的开发。微信小程序具有使用方便、快速上线、用户覆盖广等优势,成为了商家们的首选。 那么,如何快速开发一个外卖微信小程序呢?下面就让我们来看看吧! 首…...
小知识(5) el-table行样式失效问题
一、实现效果 子级呈现不同颜色去区分 二、最初代码 tips: 我这里使用的vue3 elementplus <el-table :row-class-name"tableRowClassName" >... </el-table>function tableRowClassName({ row, rowIndex }) {if (row.children.length 0) {return …...
【Docker】Docker数据的存储
默认情况下,在运行中的容器里创建的文件,被保存在一个可写的容器层里,如果容器被删除了,则对应的数据也随之删除了。 这个可写的容器层是和特定的容器绑定的,也就是这些数据无法方便的和其它容器共享。 Docker主要提…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
