java并发之并发关键字

并发关键字

关键字一:volatile

可以这样说,volatile 关键字是 Java 虚拟机提供的轻量级的同步机制

功能

volatile 有 2 个主要功能:

  • 可见性。一个线程对共享变量的修改,其他线程能够立即得知这个修改。普通变量不能做到这一点,普通变量的值在线程间传递需要通过主内存来完成。
  • 禁止指令重排序

底层原理

加入 volatile 关键字时,会多出 lock 前缀指令, 该 lock 前缀指令相当于内存屏障,内存屏障会提供 3 个功能:

  • 在执行到内存屏障这句指令时,在其前面的操作都已完成了
  • 强制将 处理器行的数据缓存写回内存
  • 一个处理器的缓存回写到内存会导致其他工作内存中的缓存失效

应用场景

  • 状态标记

    volatile + boolean

  • DCL 单例模式 (Double Check Lock,双重校验锁)

    public class Singleton {

        private volatile static Singleton singleton=null;

        private Singleton(){}

        public static Singleton getSingleton(){
            if(singleton==null){
                synchronized (Singleton.class){
                    if(singleton==null){
                        singleton=new Singleton();
                    }
                }
            }
            return singleton;
        }
    }

关键字二:synchronized

线程安全问题:

  • 存在共享数据(临界资源)
  • 存在多条线程共同操作这些共享数据

解决:同步机制

同一时刻有且只有一个线程在操作共享数据,其他线程必须等到该线程处理完数据后再对共享数据进行操作。

同步的前提:

  • 多个线程
  • 多个线程使用的是同一个锁对象

同步的弊端:

当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。

功能

使用 synchroinzed 进行同步,可以保证原子性(保证每个时刻只有一个线程执行同步代码)和可见性(对一个变量执行 unlock 操作之前,必须把变量值同步回主内存)。

使用

synchronized 修饰的对象有几种:

  • 修饰一个类。

    作用范围是 synchronized 后面括号括起来的部分

    作用对象是这个类的所有对象

    class ClassName {
       public void method() {
          synchronized(ClassName.class{
             // todo
          }
       }
    }
  • 修饰一个方法:被修饰的方法称为同步方法。

    作用范围是整个方法

    作用对象是调用这个方法的对象

    public synchronized void method(){
       // todo
    }
  • 修饰一个静态的方法。

    作用的范围是整个方法

    作用对象是这个类的所有对象

    public synchronized static void method() {
       // todo
    }
  • 修饰一个代码块:被修饰的代码块称为同步语句块

    作用范围是大括号 {} 括起来的代码块

    作用对象是调用这个代码块的对象

注意:如果锁的是类对象的话,尽管new多个实例对象,但他们仍然是属于同一个类依然会被锁住,即线程之间保证同步关系

原理

public class SynchronizedDemo {
    public static void main(String[] args) {
        synchronized (SynchronizedDemo.class//锁住类对象
        }
        method();
    }

    private synchronized static void method() //锁住类对象
    }
}

任意一个对象都拥有自己的 Monitor,当这个对象由同步块或者同步方法调用时, 执行方法的线程必须先获取该对象的 Monitor 才能进入同步块和同步方法, 如果没有获取到 Monitor 的线程将会被阻塞在同步块和同步方法的入口处,进入到 BLOCKED 状态。

synchronized 同步语句块的实现使用的是 monitorenter 和 monitorexit 指令。

monitorenter 指令指向同步代码块的开始位置,monitorexit 指令则指明同步代码块的结束位置。

使用 synchronized 进行同步,其关键就是必须要对对象的 Monitor 进行获取, 当线程获取 Monitor 后才能继续往下执行,否则就只能等待。 而这个获取的过程是互斥的,即同一时刻只有一个线程能够获取到 Monitor

上面的 SynchronizedDemo 中在执行完同步代码块之后紧接着再会去执行一个静态同步方法,而这个方法锁的对象依然就这个类对象, 那么这个正在执行的线程还需要获取该锁吗?

答案是不必的,从上图中就可以看出来, 执行静态同步方法的时候就只有一条 monitorexit 指令,并没有monitorenter 获取锁的指令。 这就是锁的重入性, 即在同一线程中,线程不需要再次获取同一把锁。 synchronized 先天具有重入性。 每个对象拥有一个计数器,当线程获取该对象锁后,计数器就会 +1,释放锁后就会将计数器 -1。

synchronized 修饰的方法并没有 monitorenter 指令和 monitorexit 指令,取得代之的是 ACC_SYNCHRONIZED 标识,该标识指明了该方法是一个同步方法,JVM 通过该 ACC_SYNCHRONIZED 访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。

锁优化策略

JDK 1.6 之后对 synchronized 进行优化。

锁的 4 种状态:无锁、偏向锁、轻量级锁、重量级锁。

1. 自旋锁

在很多应用上,共享数据的锁定状态只会持续很短一段时间。自旋锁的思想是让一个线程在请求一个共享数据的锁时执行忙循环(自旋)一段时间,如果在这段时间内能获得锁,就可以避免进入阻塞状态。

自旋锁虽然能避免进入阻塞状态从而减少开销,但是它需要进行忙循环操作占用 CPU 时间,它只适用于共享数据的锁定状态很短的场景。

在 JDK 1.6 中引入了自适应的自旋锁。自适应意味着自旋的次数不再固定了,而是由前一次在同一个锁上的自旋次数及锁的拥有者的状态来决定。

2. 锁消除

锁消除是指对于被检测出不可能存在竞争的共享数据的锁进行消除

锁消除主要是通过逃逸分析来支持,如果堆上的共享数据不可能逃逸出去被其它线程访问到,那么就可以把它们当成私有数据对待,也就可以将它们的锁进行消除。

对于一些看起来没有加锁的代码,其实隐式的加了很多锁。例如下面的字符串拼接代码就隐式加了锁:

public static String concatString(String s1, String s2, String s3) {
    return s1 + s2 + s3;
}Copy to clipboardErrorCopied

String 是一个不可变的类,编译器会对 String 的拼接自动优化。在 JDK 1.5 之前,会转化为 StringBuffer 对象的连续 append() 操作:

public static String concatString(String s1, String s2, String s3) {
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    sb.append(s3);
    return sb.toString();
}Copy to clipboardErrorCopied

每个 append() 方法中都有一个同步块。虚拟机观察变量 sb,很快就会发现它的动态作用域被限制在concatString() 方法内部。也就是说,sb 的所有引用永远不会逃逸到 concatString() 方法之外,其他线程无法访问到它,因此可以进行消除。

3. 锁粗化

如果一系列的连续操作都对同一个对象反复加锁和解锁,频繁的加锁操作就会导致性能损耗

上一节的示例代码中连续的 append() 方法就属于这类情况。如果虚拟机探测到由这样的一串零碎的操作都对同一个对象加锁,将会把加锁的范围扩展(粗化)到整个操作序列的外部。对于上一节的示例代码就是扩展到第一个 append() 操作之前直至最后一个 append() 操作之后,这样只需要加锁一次就可以了。

4. 偏向锁

在大多数情况下,锁不仅不存在多线程竞争,而且总是由同一个线程多次获得。偏向锁的思想是偏向于第一个获取锁对象的线程,这个线程在之后获取该锁就不再需要进行同步操作,甚至连 CAS 操作也不再需要。

5. 轻量级锁

轻量级锁是由偏向锁升级而来,偏向锁运行在一个线程进入同步块的情况下,当第二个线程加入锁争用的时候,偏向锁就会升级为轻量级锁。

对于绝大部分的锁,在整个同步周期内都是不存在竞争的,因此也就不需要都使用互斥量进行同步,可以先采用 CAS 操作进行同步,如果 CAS 失败了再改用互斥量进行同步。

volatile 与 synchronized 比较

  • volatile 是 JVM 轻量级的同步机制,所以性能比 synchronized 要好

  • volatile 只能修饰变量

    synchronized 可以修饰代码块或者方法

  • 多线程访问 volatile 不会出现阻塞

    synchronized 会出现阻塞

  • volatile 只能保证可见性,不能保证原子性

    synchroinzed 能保证原子性,也间接保证了可见性

  • volatile 修饰的变量不会被编译器优化

    synchronized 修饰的变量可以被编译器优化

获取更多干货内容,记得关注我哦。

本文由 mdnice 多平台发布

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

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

相关文章

从零开始学习PX4源码5(遥控器数据)

#目录 文章目录 摘要1.PX4 遥控器控制整体流程2.PX4 遥控器输入程序3.PX4 遥控器数据外部调用接口4.PX4 遥控器手动(姿态控制)变量5.遥控器数据整体流程摘要 本节主要记录PX4代码中如何获取遥控器数据,遥控器数据如何被外界调用的过程,欢迎批评指正。 1.PX4 遥控器控制整…

JAVA-StringBuilder和StringBuffer

一、认识String类 1.认识 String在Java中是字符串类型,但与其他类型不同。它是一个类,可以创建对象的类。与int、char等自待类型有些许不同。但它仍然是java提供的一种类型。 类中有4个属性,这里主要认识一下value属性。它是实际存放字符串…

2024 IDEA软件 部署tomcat 十二步 运行web页面(html类似的)(中英文对照版本)新手小白易上手

目录 一、准备工作(三必备): 1、自己的web项目 2、idea软件(我是2023.1.2版本) 3、tomcat X.X版本 二 、正式开始步骤,不废话!! 1、 点击菜单栏中 “File”(文件&…

NASA数据集:ATLAS/ICESat-2 L3A 海洋地表高度 V006

ATLAS/ICESat-2 L3A Ocean Surface Height V006 目录 简介 摘要 代码 引用 网址推荐 0代码在线构建地图应用 机器学习 简介 该数据集(ATL12)包含全球开阔洋(包括无冰季节冰区和近海岸地区)的沿轨海面高度。 还提供了高度…

C++ 9.25

手动实现栈、和队列 stack #include <iostream> using namespace std; class Stack { private: int* arr; // 存储栈元素的数组 int top; // 栈顶索引 int capacity; // 栈的容量 public: Stack(int size) { arr new int[size]; c…

FLStudio21Mac版flstudio v21.2.1.3430简体中文版下载(含Win/Mac)

给大家介绍了许多FL21版本&#xff0c;今天给大家介绍一款FL Studio21Mac版本&#xff0c;如果是Mac电脑的朋友请千万不要错过&#xff0c;当然我也不会忽略掉Win系统的FL&#xff0c;链接我会放在文章&#xff0c;供大家下载与分享&#xff0c;如果有其他问题&#xff0c;欢迎…

基于Python大数据的音乐推荐及数据分析可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

【吊打面试官系列-MySQL面试题】MySQL 数据库作发布系统的存储,一天五万条以上的增量,预计运维三年,怎么优化?

大家好&#xff0c;我是锋哥。今天分享关于【MySQL 数据库作发布系统的存储&#xff0c;一天五万条以上的增量&#xff0c;预计运维三年,怎么优化&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; MySQL 数据库作发布系统的存储&#xff0c;一天五万条以上的增量…

二模--解题--101-110

文章目录 10.沟通管理101、 [单选] 在项目执行阶段&#xff0c;项目经理意识到项目干系人一直延迟答复敏感性电子邮件。项目经理应该怎么做&#xff1f; 4.整合管理102、 [单选] 在编制项目章程用于批准时&#xff0c;项目经理发现有两名干系人对关键可交付成果的期望有冲突。若…

【读写分离?聊聊Mysql多数据源实现读写分离的几种方案】

文章目录 一.什么是MySQL 读写分离二.读写分离的几种实现方式(手动控制)1.基于Spring下的AbstractRoutingDataSource1.yml2.Controller3.Service实现4.Mapper层5.定义多数据源6.继承Spring的抽象路由数据源抽象类&#xff0c;重写相关逻辑7. 自定义注解WR&#xff0c;用于指定当…

Linux-TCP重传

问题描述&#xff1a; 应用系统进行切换&#xff0c;包含业务流量切换&#xff08;即TongWeb主备切换&#xff09;和MYSQL数据库主备切换。首先进行流量切换&#xff0c;然后进行数据库主备切换。切换后发现备机TongWeb上有两批次慢请求&#xff0c;第一批慢请求响应时间在133…

【探索智谱AI的CogVideoX:视频生成的新前沿】

2024年8月6日&#xff0c;智谱AI宣布其开源视频生成模型CogVideoX&#xff0c;激发了开发者的创造力和对新技术的期待。 一、CogVideoX模型概述 CogVideoX 是一款先进的视频生成工具&#xff0c;可基于最长 226 个 token 的提示生成视频&#xff0c;时长可达 6 秒&#xff0c;…

0基础学习PyTorch——时尚分类(Fashion MNIST)训练和推理

大纲 环境准备安装依赖下载训练集训练定义模型训练加载训练集定义损失函数和优化器训练模型保存模型完整文件 推理加载模型加载并预处理本地文件推理完整文件 代码地址参考资料 时尚分类是PyTorch官方文档中推荐的案例。本文将拆解这个案例&#xff0c;进行部署以及测试。 环境…

电路板上电子元件检测系统源码分享

电路板上电子元件检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comp…

SpringCloud源码:客户端分析(二)- 客户端源码分析

背景 我们继续分析EurekaClient的两个自动化配置类&#xff1a; 自动化配置类功能职责EurekaClientAutoConfiguration配置EurekaClient确保了Eureka客户端能够正确地&#xff1a;- 注册到Eureka服务端- 周期性地发送心跳信息来更新服务租约- 下线时通知Eureka服务端- 获取服务实…

TypeScript 设计模式之【建造者模式】

文章目录 **建造者模式**&#xff1a;打造你的梦想之屋建造者的秘密建造者有什么利与害&#xff1f;如何使用建造者搭建各种房子代码实现案例建造者模式的主要优点建造者模式的主要缺点建造者模式的适用场景总结 建造者模式&#xff1a;打造你的梦想之屋 假设你想要一栋完美的…

SpringBoot代码实战(MyBatis-Plus+Thymeleaf)

构建项目 修改pom.xml文件&#xff0c;添加其他依赖以及设置 <!--MyBatis-Plus依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.6</version><…

LiveGBS流媒体平台GB/T28181功能-支持电子放大拉框放大直播视频拉框放大录像视频流拉框放大电子放大

LiveGBS流媒体平台GB/T28181功能-支持电子放大拉框放大直播视频拉框放大录像视频流拉框放大电子放大 1、直播播放2、录像播放3、搭建GB28181视频直播平台 1、直播播放 国标设备-》查看通道-》播放 &#xff0c;左键单击可以拉取矩形框&#xff0c;放大选中的范围&#xff0c;释…

序列化流(对象操作输出流)反序列化流(对象操作输入流)

可以把Java中的对象写到本地文件中 序列化流&#xff08;对象操作输出流&#xff09; 构造方法 成员方法 使用对象输出流将对象保存到文件会出现NotSerializableException异常 解决方案&#xff1a;需要让Javabean类实现Serializable接口 Student package myio;import java.…

家政服务预约系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;客户管理&#xff0c;员工管理&#xff0c;家政服务管理&#xff0c;服务预约管理&#xff0c;员工风采管理&#xff0c;客户需求管理&#xff0c;接单信息管理 微信端账号功能包括&#xff1a;系统首…