【多线程学习6】synchronized关键字

news2024/9/24 23:22:01

【多线程学习6】synchronized关键字

一、synchronized关键字是什么?有什么作用?

synchronized关键字是Java线程同步的关键字其可以修饰方法或代码块,并可以保证其修饰的方法代码块在任意时刻只能有一个线程执行

synchronized关键字使用主要有下面3种:

  • 修饰代码块
  • 修饰实例方法
  • 修饰静态方法

其中
synchronized关键字加到static静态方法和synchronized(class)代码块上都是给class类上锁。
synchronized关键字加到实例方法或synchronized(object)上是给对象实例上锁。

1、synchronized修饰代码块(锁指定对象/类)

    private static final Object object1 = new Object();
     public static void deal1() {
        //同步代码,获取对象锁
         synchronized (object1) {
            //需要同步的操作
        }
        
        //同步代码,获取class类锁
        synchronized (practice3.class) {
             //需要同步的操作
        }
    }

2、synchronized修饰实例方法(锁当前对象实例)

给当前对象实例加锁,进入同步代码前要获得当前对象实例的锁

    public synchronized void dealIt() {
        //需要同步的操作
    }

3、synchronized修饰静态方法(锁当前类)

当前类加锁,进入同步代码块前要获得当前class的锁(会作用于类的所有对象实例)。
因为静态成员不属于任何一个实例对象,归整个类所有,不依赖于类的特定实例,所以被类的所有实例共享。

    public synchronized static void dealIt() {
        //需要同步的操作
    }

问题思考1:

被synchronized修饰的静态方法和非静态方法之间调用互斥吗?
答:
不互斥,如果线程A调用的是实例对象所属的类的静态synchronized方法,线程B调用的是实例对象的非静态synchronized方法,是允许的,不会发生互斥现象,因为访问静态synchronized方法占用的锁是当前类的锁,而非静态synchronized方法所占用的锁是当前实例对象的锁

问题思考2:

构造方法可以使用synchronized修饰吗?
答:
构造方法不能使用synchronized关键字修饰
因为构造方法本身就属于线程安全的,不存在同步构造方法一说。

二、synchronized底层原理

1、对于synchronized同步代码块情况

public class synchronized1{
	public void deal() {
		synchronized(synchronized1.class) {
			System.out.println("Hello wys");
		}
	}
}

执行反编译,并查看反编译后的内容
在这里插入图片描述

在这里插入图片描述

说明:先将.java文件编辑为.class字节码文件,然后将.class文件反编译查看其反编译后的内容,反编译后的内容如下:
在这里插入图片描述
从上面反编译后的内容中我们可以看到:synchronized同步语句块是通过使用 monitorentermonitorexit两个指令。其中monitorenter指令指向同步代码块的开始位置monitorexit指令则指向同步代码块的结束位置

在执行monitorenter时,当前线程会尝试获取锁对象的monitor的持有权(对象监视器monitor),当monitor里的计数器为0就可以获取,并将计数器加1。如果当前线程获取锁失败,那当前线程就要阻塞等待,直到锁被另一个线程释放为止。

在执行monitorexit指令后,将锁计数器设为0,表示锁被释放,其他线程可以尝试获取锁。(注意:当前线程拥有锁对象才能执行monitorexit指令)

2、synchronized修饰方法的情况

public class synchronized1{
	public synchronized void deal1() {
			System.out.println("Hello wys");
	}
}

在这里插入图片描述
我们从反编译的结果可以看到,synchronized修饰方法并没有monitorenter指令和monitorexit指令,取而代之使用的是ACC_SYNCHRONIZED标识。该标识指明此方法为一个同步方法。JVM通过该标识ACC_SYNCHRONIZED标识来辨别一个方法是否为同步方法,从而进行相应的同步调用。

如果是实例方法,JVM会尝试获取实例对象的锁,如果是静态方法JVM会尝试获取当前class的锁。

总结:

  • 1、synchronized同步代码块底层实现是通过monitorentermonitorexit指令,其中monitorenter指令指向同步代码块的开始位置,monitorexit指令则指明同步代码块的结束位置。
  • 2、synchronized修饰方法并没有monitorenter和monitorexit指令,取而代之的是ACC_SYNCHRONIZED标识,该标识指明了该方法是一个同步方法。
  • 不过两者的本质都是对对象监视器monitor的获取。

三、synchronized和volatile有什么区别?

synchronized关键字 和 volatile关键字 两者是互补存在的而不是对立存在的

  • volatile关键字是线程同步的轻量级实现。volatile关键字可以保证变量的可见性,但是不能保证对变量操作的原子性。而synchronized关键字两者都能保证
  • volatile关键字只能修饰变量,而synchronized关键字可以修饰方法和代码块
  • volatile主要是用于解决多线程环境下变量的可见性,而synchronized主要是用于解决多线程环境下访问资源的同步性

四、JDK1.6之后synchronized底层做了哪些优化?

JDK1.6对锁的实现引入了大量的优化,如如偏向锁、轻量级锁、自旋锁、适应性自旋锁、锁消除、锁粗化等技术来减少锁操作的开销。

加入偏向锁和轻量锁后,锁就有四种状态级别由低到高:无锁-》偏向锁-》轻量级锁-》重量级锁。

具体详细优化内容后续文章介绍

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

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

相关文章

关于HIVE的分区与分桶

1.分区 1.概念 Hive中的分区就是把一张大表的数据按照业务需要分散的存储到多个目录,每个目录就称为该表的一个分区。在查询时通过where子句中的表达式选择查询所需要的分区,这样的查询效率会提高很多 个人理解白话:按表中或者自定义的一个列,对数据进…

筛选给定范围内的日志

目录 1.时间戳 2.实例 1.首先创建ubuntu.log日志 2.写dem.awk创建规则 3.筛选 1.时间戳 一个能表示一份数据在某个特定时间之前已经存在的、 完整的、 可验证的数据,通常是一个字符序列,唯一地标识某一刻的时间。 awk提供了mktime()函数,它可以将时间…

macbook怎么卸载软件?2023年最新全新解析macbook电脑怎样删除软件

macbook怎么卸载软件?2023年最新全新解析macbook电脑怎样删除软件。关于Mac笔记本如何卸载软件_Mac笔记本卸载软件的四种方法的知识大家了解吗?以下就是小编整理的关于Mac笔记本如何卸载软件_Mac笔记本卸载软件的四种方法的介绍,希望可以给到…

像素画教程:立体感与“84渐变法“

像素画本身没有什么困难,是矢量图简笔画之外最简单、而又最容易产生美术效果的画风。 然而,细节难以描绘、立体感难表现、画面易单调成了像素画绘制过程中的常见困难。 这篇文章或许不能保证每个人都能熟练掌握、运用像素画,但至少可以抛砖引…

任务14、无缝衔接,MidJourney瓷砖(Tile)参数制作精良贴图

14.1 任务概述 在这个实验任务中,我们将深入探索《Midjourney Ai绘画》中的Tile技术和其在艺术创作中的具有挑战性的应用。此任务将通过理论学习与实践操作相结合的方式,让参与者更好地理解Tile的核心概念,熟练掌握如何在Midjourney平台上使用Tile参数,并实际运用到AI绘画…

【雕爷学编程】Arduino动手做(184)---快餐盒盖,极低成本搭建机器人实验平台

吃完快餐粥,除了粥的味道不错之外,我对个快餐盒的圆盖子产生了兴趣,能否做个极低成本的简易机器人呢?也许只需要二十元左右 知识点:轮子(wheel) 中国词语。是用不同材料制成的圆形滚动物体。简…

Dockerfile定制Tomcat镜像

Dockerfile中的打包命令 FROM : 以某个基础镜像作为此镜像的基础 RUN : RUN后面跟着linux常用命令,如RUN echo xxx >> xxx,注意,RUN 不能用于执行命令,因为每个RUN都是独立运行的,RUN 的cd对镜像中的…

Python求均值、方差、标准偏差SD、相对标准偏差RSD

均值 均值是统计学中最常用的统计量,用来表明资料中各观测值相对集中较多的中心位置。用于反映现象总体的一般水平,或分布的集中趋势。 import numpy as npa [2, 4, 6, 8]print(np.mean(a)) # 均值 print(np.average(a, weights[1, 2, 1, 1])) # 带…

Godot4 C# vscode开发环境搭建

这里写自定义目录标题 软件Godot配置vscode配置结果参考 软件 Godot .Net版本: 下载链接vscode :自行下载.netcore7:.netcore6可能也行vscode插件: Godot配置 1.配置文件用VSCode打开 2.生成C#项目 项目–>工具–>C#->Create C# Solution&…

Python 关于模块的几点介绍 。和。。和__all__和__main___和__file__

./ 是意思让解释器去引用当前目录下的内容 ../ 是意思让解释器去引用上层目录下的内容 __all__ 用来定义我们导出的内容可以有哪些的一个编码方式 flake8 可以检测代码的安全隐患,在python中 if __name__ __main__ 现在有两个文件,分别为&a…

【Unity3D】花瓣特效

1 花瓣绘制原理 如下图是实现的花瓣特效效果,为方便描述,我们将每个红色的扁状长条称为花瓣,每个花瓣中心的绿点称为花蕊,花朵的正中心称为花心。 我们在 xOz 平面上绘制花朵,假设花心为 O 点,其世界坐标为…

JVM之类加载与字节码

1.类文件结构 一个简单的HelloWorld.Java package cn.itcast.jvm.t5; // HelloWorld 示例 public class HelloWorld { public static void main(String[] args) { System.out.println("hello world"); } }编译为 HelloWorld.class 后的样子如下所示: […

CentOS安装podman-compose

1. 安装python3的依赖 yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel libffi-devel 如果当前登录的是普通用户,需要在命令前加sudo,否则不用&…

C++实用技术(二)std::function和bind绑定器

目录 简介std::functionstd::function对象包装器std::function做回调函数 std::bind绑定器bind绑定普通函数bind绑定成员函数 简介 C11新增了std::function和std::bind。用于函数的包装以及参数的绑定。可以替代一些函数指针,回调函数的场景。 std::function std…

git 版本控制与合并

一 git概述: - Git是一种分布式版本控制系统,用于跟踪和管理软件开发项目中的代码变更。 - 它允许多人协同工作,记录代码历史变更,并轻松管理多个项目版本。 **Git的主要特点**包括: 1. **分布式系统**:…

嵌入式开发学习(STC51-14-时钟)

内容 在数码管上显示时间,时分秒,格式为“XX-XX-XX”; DS1302时钟芯片介绍 简介 DS1302是DALLAS公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31字节静态RAM,通过简单的串行接口与单片机进行通信&#xf…

系统架构设计高级技能 · 软件架构概念、架构风格、ABSD、架构复用、DSSA(一)【系统架构设计师】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 设计模式系列 期待你的关注哦!!! 现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。 Now everythin…

第4集丨Vue 江湖 —— 计算属性

目录 一、基本使用1.1 在computed中定义1.1.1 案例1.1.2 控制台调用getter1.1.3 控制台中的data和computed 1.2 缓存效果1.3 完整写法1.3.1 案例1.3.2 效果图 1.4 简写形式 二、案例的其他实现2.1 methods实现2.2 插值语法实现 三、体会计算属性的好处3.1 复杂任务时3.2 使用计…

IO模型-信号驱动IO

linux内核中存在一个信号SIGIO,这个信号就是用于实现信号驱动IO的。当应用程序中想要以信号驱动IO的模型读写硬件数据时,首先注册一个SIGIO信号的信号处理函数,当硬件数据就绪,硬件会发起一个中断,在硬件的中断处理函数中向当前进…

求解n阶勒让德多项式的值

描述 用递归方法求n阶勒让德多项式的值,递归公式为: 在主函数中输入一个整数n和一个实数x,调用函数 legendre(n,x),并输出其返回值。 输入 第一行输入一个整数n,表示阶数;第二行输入一个实数x。 输出 …