并发编程线程安全之同步锁Synchronized

news2025/1/17 21:39:24

一、原子性定义

原子性的本质是互斥访问,同一时刻只有一个线程对它进行访问操作

二、原子性问题的简述

public class AutomicDemo {

    int count = 0;
    public static void main(String[] args) throws InterruptedException {

        AutomicDemo automicDemo = new AutomicDemo();


        Thread thread1 = new Thread(() ->
        {
            for (int j = 0; j < 1000; j++) {
                automicDemo.incr();
            }
        });

        Thread thread2 = new Thread(() ->
        {
            for (int j = 0; j < 1000; j++) {
                automicDemo.incr();
            }
        });

        thread1.start();
        thread2.start();
        // join方法保证线程执行完毕
        thread1.join();
        thread2.join();
        System.out.println("i的结果值为:"+automicDemo.count);
    }


    public void incr(){
        count++;
    }
}

运行结果:

线程1线程2各循环一千次执行i++操作,正常情况下应该得到的值是2000,那么为什么会得到1412呢?这是由于当前代码中的i++操作是非原子性的。

其实一个count++操作是分为3步的:1.加载2.计算3.写入内存。由上图可以看出来,在同一时刻,线程A与线程B同时运行,当线程A刚把count为0的值加载到寄存器的时候,此时线程进行了切换,线程B完成了整个count++操作并把结果写入了内存,此时线程A接着执行,那么线程A加载到寄存器的count还是0,因此它计算后也把count=1存入了内存,这无形中就少了一次计算。思考:那么应该怎么解决这个问题呢?加同步锁synchronized关键字,保证在同一时刻,只有一个线程能够访问并操作count++       

思考:   为什么加了synchronized关键字 系统就会认定它为一个同步锁呢,从而避免多线程对该方法 的一个操作呢?(见3.3)synchronized的作用范围是什么呢?(见3.1)锁的本质又是什么呢?(见3.2)

三、Synchronized关键字

3.1 作用范围

  • 修饰实例方法  创建不同的对象,都可以访问该实例
  • 修饰静态方法   全局锁
  • 修饰代码块

synchronized() 括号中可以存储任何一个对象, 影响锁的作用范围,其实就是括号中对象的生命周期

3.2 抢占锁的本质

抢占锁的本质就是如何实现互斥,那么必定有两个条件

  • 共享资源
  • 锁标记  可以假设 0代表无锁  1 代表有锁

也就是说,抢占锁,一定是共同要访问一个共享的资源,当一个线程先占有了这个资源,就变为有锁状态,阻塞其它的线程。

3.3 锁信息的存储

加了synchronized关键字,系统为何就能识别这是一个同步锁呢,其实,系统根据该关键字,保存了一些信息在作用的对象上。

MarkWord对象头

我们可以通过以下代码打印对象头的信息(不加synchronized和加synchronized的区别)

   public static void main(String[] args) {
        Object lock = new Object();
        System.out.println(VM.current().details());
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());
    }

打印的信息如下

结合下图可以看出,第一行的前8个字节的最后3位001 则为无锁状态

四、Synchronized锁升级

1. 无锁状态

2. 偏向锁: 假设没有线程竞争的时候,A线程进入到同步代码 就会偏向A线程 有线程竞争的时候 线程B再进来 就会做升级 轻量级锁

3. 轻量级锁   主要作用是避免线程阻塞   采用自旋锁的方式

4 .重量级锁   表示的是用户态到内核态的交换  没有获得锁的线程会阻塞,再被唤醒

思考: 线程A已经抢占到了锁,当线程B来竞争的时候,如果是重量级锁,则线程A执行完还需要唤醒线程B, 比较消耗性能,那么有没有一种办法可以避免或者优化这种阻塞呢?于是就引入了轻量级锁,线程B会不断的去重试,如果此时正好线程A结束了,那么线程B就可以执行了,不需要再去唤醒了。举个例子,就比如你去找老王,会先敲几下门,然后如果门没开,则会再去一边等着,等着老王来唤醒。

分析: 当有两个线程的时候,线程A先进入了,则线程B抢占锁的时候,则会先进行自旋,如果抢占到了,则修改lock flag的标记,使用CAS机制保证操作的原子性

五、CAS机制

old: ThreadA

expect: ThreadB

update: ThreadC

CAS机制与乐观锁类似

CAS机制其底层是C++代码,采用了lock指令

举例:

当前线程A获得了偏向锁,线程B来抢占偏向锁

线程B就会来调用CAS,把偏向锁的指针指向自己

CAS(object,线程A的指针,线程B的指针(带更新的值))

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

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

相关文章

洛谷C++简单题小练习day15—计算阶乘小程序(不用循环)

day15--计算阶乘小程序--2.19 习题概述 题目描述 求 n!&#xff0c;也就是 123⋯n。 挑战&#xff1a;尝试不使用循环语句&#xff08;for、while&#xff09;完成这个任务。 输入格式 第一行输入一个正整数 n。 输出格式 输出一个正整数&#xff0c;表示 n! 代码部分 …

MySQL数据库基础(十一):多表查询

文章目录 多表查询 一、交叉连接&#xff08;了解&#xff09; 二、内连接 1、连接查询的介绍 2、内连接查询 3、小结 三、左外连接 1、左连接查询 2、小结 四、右外连接 1、右连接查询 2、小结 多表查询 一、交叉连接&#xff08;了解&#xff09; 它是所有连接…

Elasticsearch:将 IT 智能和业务 KPI 与 AI 连接起来 - 房间里的大象

作者&#xff1a;Fermi Fang 大象寓言的智慧 在信息技术和商业领导力的交叉点&#xff0c;蒙眼人和大象的古老寓言提供了一个富有洞察力的类比。 这个故事起源于印度次大陆&#xff0c;讲述了六个蒙住眼睛的人第一次遇到大象的故事。 每个人触摸大象的不同部位 —— 侧面、象牙…

Leetcode日记 226. 翻转二叉树 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

Leetcode日记 226. 翻转二叉树 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 二叉树简介二叉树分类解题方法制作不易&#xff0c;感谢三连&#xff0c;谢谢啦 二叉树简介 二叉树&#xff08;Binary Tree&#xff09;是一种特殊的树形…

UE蓝图 分支(Branch)节点和源码

系列文章目录 UE蓝图 Cast节点和源码 UE蓝图 分支(Branch)节点和源码 文章目录 系列文章目录一、分支节点功能二、分支节点用法三、分支节点使用场景四、分支节点实现过程五、分支节点相关源码 一、分支节点功能 在Unreal Engine&#xff08;UE&#xff09;的蓝图中&#xff0…

leetcode1049:最后一块石头的重量二

解题思路&#xff1a; 把石头堆分割成差不多的两堆&#xff0c;使得两堆差值最小 dp数组的含义&#xff1a; dp[j]:背包容量为j的背包最大重量(价值)为dp[j] dp[j] max(dp[j],dp[j-stones[i]] stones[i]) 初始化&#xff1a;&#xff08;dp数组的大小根据题目进行定义&a…

华为配置旁挂二层组网隧道转发示例

配置旁挂二层组网隧道转发示例 组网图形 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件扩展阅读 业务需求 企业用户通过WLAN接入网络&#xff0c;以满足移动办公的最基本需求。且在覆盖区域内移动发生漫游时&#xff0c;不影响用户的业务使用。 组网需求 AC组…

【总结】linux命令行在个人用户下添加环境变量

一&#xff0c;简介 在工作过程中需要将对应的路径添加到个人用户的环境变量中&#xff0c;本文介绍如何添加&#xff0c;供参考。 二&#xff0c;操作步骤 非常简单&#xff0c;只需要找到对应配置文件&#xff0c;将路径添加进去即可。 2.1 找到配置文件 一般为用户名下…

【无标题】力扣报错:member access within null pointer of type ‘struct ListNode‘

项目场景&#xff1a; 做单链表反转题目&#xff0c;报错&#xff1a;member access within null pointer of type ‘struct ListNode’ 题目链接:LINK 问题描述 我明明在初始化指针时候&#xff0c;已经处理了n2->next情况却依然报错 这个报错提示含义是&#xff1a;大概就…

react封装通用Modal弹窗组件

目录 1、【src/component/modal/hoc.js】 2、【src/component/modal/componentModal.js】 3、【src/page/projectView.js】 【说明】&#xff1a;后台管理的项目中会经常遇到弹窗&#xff0c;于是封装了一个简单的公共弹窗组件 这个公共组件不适用复杂的功能&#xff0c;简单的…

力扣题目训练(17)

2024年2月10日力扣题目训练 2024年2月10日力扣题目训练551. 学生出勤记录 I557. 反转字符串中的单词 III559. N 叉树的最大深度241. 为运算表达式设计优先级260. 只出现一次的数字 III126. 单词接龙 II 2024年2月10日力扣题目训练 2024年2月10日第十七天编程训练&#xff0c;今…

第五次作业(防御安全)

需求: 1.办公区设备可以通过电信链路和移动链路上网&#xff08;多对多的NAT&#xff0c;并且需要保留一个公网IP 不能用来转换&#xff09; 2.分公司设备可以通过总公司的移动链路和电信链路访问到DMZ区的http服务器 3.分公司内部的客户端可以通过公网地址访问到内部的服务…

力扣OJ题——相交链表

题目&#xff1a;160. 相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 思路一&#xff08;暴力求解&#xff09;&#xff1a; A链表的每个节点依次跟B链表中节点进行…

xshell 修改时间破解使用

文章目录 xshell 修改时间破解使用:question: 问题:point_right: 解决方案&#xff1a; xshell 修改时间破解使用 参考地址&#xff1a;博客地址 ❓ 问题 问题 ​ 当前 xshell 官方提供免费的个人版本供使用&#xff0c;但是在官网升级新版本后则需要进行升级之后才能使用&…

调用接口时不时出现 Error: socket hang up

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 今天采用golang创建了一个http服务&#xff0c;准备对若干接口进行测试。 问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 在测试第一个接口时&#xff0c;发现采用postman调用接口…

Fisher-Yates乱序算法

乱序算法 public class Test07 {public static void main(String[] args) {//乱序算法int[] arr {1,2,3,4,5,6,7,8};//逆序遍历 且这个随机的下标不能使要交换的元素的本身for(int i arr.length-1;i>0;i--){//产生一个随机的下标与当前元素进行交换int index (int)(Math…

文件包含+文件上传漏洞(图片马绕过)

目录 一.文件包含二.文件上传三.图片马四.题目 一.文件包含 将已有的代码以文件形式包含到某个指定的代码中&#xff0c;从而使用其中的代码或者数据&#xff0c;一般是为了方便直接调用所需文件&#xff0c;文件包含的存在使得开发变得更加灵活和方便&#xff08;若对用户输入…

【无刷电机学习】基础概念及原理入门介绍

目录 0 参考出处 1 定义 2 各种电机优势比较 2.1 有刷与无刷比较 2.2 交流与直流比较 2.3 内转子与外转子比较 2.4 低压BLDC的一些优点 3 基本原理 3.1 单相无刷电机 3.2 三相无刷电机 4 驱动方法 4.1 六步换相控制 4.2 正弦波控制 5 转子位置信息的获取 5…

安卓游戏开发之图形渲染技术优劣分析

一、引言 随着移动设备的普及和性能的提升&#xff0c;安卓游戏开发已经成为一个热门领域。在安卓游戏开发中&#xff0c;图形渲染技术是关键的一环。本文将对安卓游戏开发中常用的图形渲染技术进行分析&#xff0c;比较它们的优劣&#xff0c;并探讨它们在不同应用场景下的适用…

辽宁博学优晨教育:引领视频剪辑新风尚,打造教育界的剪辑大师

在数字化时代&#xff0c;视频剪辑已经成为一项不可或缺的技能。辽宁博学优晨教育凭借其卓越的教学质量和实践经验&#xff0c;成功开启了视频剪辑培训的新篇章&#xff0c;为广大学习者提供了一个可靠的学习平台。今天&#xff0c;就让我们一起走进博学优晨教育&#xff0c;探…