【并发】并发锁机制-深入理解synchronized(一)

news2024/11/28 23:57:16

【并发】并发锁机制-深入理解synchronized(一)

synchronized 基础篇(使用)

一、Java共享内存模型带来的线程安全问题

1. 代码示例

2. 运行结果

3. 问题分析

4. 临界区(Critical Section)

5. 竞态条件(Race Condition)

二、synchronized 的使用

1. 同步普通(实例)方法

2. 同步静态方法

3. 同步this实例对象

4. 同步类对象

5. 同步对象实例

解决之前的共享问题

遗留问题(高级篇种解释)

下一节——synchronized 高级篇(底层原理)​​​​​​​


【并发】并发锁机制-深入理解synchronized(一)

这一篇文章主要介绍synchronized的使用和其底层原理!我将会由浅入深带大家学习synchronized!

synchronized 基础篇(使用)

一、Java共享内存模型带来的线程安全问题

思考: 两个线程对初始值为 0 的静态变量一个做自增,一个做自减,各做 5000 次,结果是 0 吗?

1. 代码示例

public class SyncDemo {

    private static int counter = 0;

    public static void increment() {
        counter++;
    }

    public static void decrement() {
        counter--;
    }

    public static void main(String[] args) throws InterruptedException {
        // 线程一
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                increment();
            }
        }, "t1");

        // 线程二
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                decrement();
            }
        }, "t2");
        t1.start();
        t2.start();
        // main线程 要等到t1、t2线程 运行结束后才会终止
        t1.join();
        t2.join();

        System.out.println("counter = " + counter);
    }
}

2. 运行结果

以上的结果可能是正数、负数、零(但是为0,基本是不可能出现的!)

3. 问题分析

Java 中对静态变量自增,自减不是原子操作

我们可以查看 i++ i--(i 为静态变量)的 JVM 字节码指令 

i++的JVM 字节码指令

getstatic i    // 获取静态变量i的值

iconst_1     // 将int常量1压入操作数栈

iadd           // 自增

i--的JVM 字节码指令

getstatic i    // 获取静态变量i的值

iconst_1      // 将int常量1压入操作数栈

isub             // 自减

如果单线程情况下,这些JVM指令顺序执行,(不交错)那肯定是没有问题的。

但是,在多线程下,可能会交错运行

4. 临界区(Critical Section)

一个程序运行多个线程本身是没有问题的!问题出在多个线程访问共享资源

多个线程(只)读共享资源其实也没有问题

在多个线程对共享资源读写操作时发生指令交错,就会出现问题!!!

一段代码块内如果存在对共享资源的多线程读写操作,称这段代码块为临界区,其共享资源为临界资源

例如,我们上述的代码中的如下部分: 

//临界资源
private static int counter = 0;

public static void increment() { //临界区
    counter++;
}

public static void decrement() {//临界区
    counter--;
}

5. 竞态条件(Race Condition)

多个线程临界区内执行,由于代码的执行序列不同而导致结果无法预测,称之为发生了竞态条件

为了避免临界区的竞态条件发生,有多种手段可以达到目的:

  • 阻塞式的解决方案:synchronized(本章节重点),Lock
  • 非阻塞式的解决方案:原子变量(Atomic原子类,CAS)

 需要注意的是,在Java中同步和互斥的场景都是使用synchronized实现的!但它们是有区别的!

  • 互斥是保证临界区的竞态条件发生,同一时刻只能有一个线程执行临界区代码
  • 同步是由于线程执行的先后、顺序不同、需要一个线程等待其它线程运行到某个点 

二、synchronized 的使用

synchronized 同步块是 Java 提供的一种原子性内置锁,Java 中的每个对象都可以把它当作一个同步锁来使用,这些 Java 内置的使用者看不到的锁被称为内置锁,也叫作监视器锁

大致是有 5种用法

1. 同步普通(实例)方法

public synchronized void method() {
    ...
}

2. 同步静态方法

public static synchronized void method() {
    ...
}

3. 同步this实例对象

synchronized(this) {
    ...
}

4. 同步类对象

synchronized(synchronizedDemo.class){
    ...
}

5. 同步对象实例

String lock = "";
synchronized(lock){
    ...
}

解决之前的共享问题

方法一: 

private static int counter = 0;

public static synchronized void increment() {
    counter++;
}

public static synchronized void decrement() {
    counter--;
}

方法二:

private static int counter = 0;
private static String lock = "";

public static void increment() {
    synchronized (lock) {
        counter++;
    }
}

public static void decrement() {
    synchronized (lock) {
        counter--;
    }
}

synchronized 实际是用对象锁保证了临界区内代码的原子性 

遗留问题(高级篇种解释)

同步实例对象和同步类对象有什么区别? 

这5种方式在性能上面是否有差别? 

下一节——synchronized 高级篇(底层原理)

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

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

相关文章

【Go】内存模型中的内存可见性

前言 使用go必然会使用到协程以及其他的并发操作&#xff0c;初期学习的时候&#xff0c;经常在启动协程时操作变量出现问题&#xff0c;要么就是变量没更新&#xff0c;要么就是各种崩溃&#xff0c;或者vscode报告警之类的&#xff0c;于是浅看了一下Go的内存模型&#xff0…

离散制造业ERP系统对生产物料管理有哪些帮助?

在离散制造企业生产加工过程中&#xff0c;生产物料管理是一个至关重要的环节。车间物料能不能管控好&#xff0c;影响着整个产品的品质、工作效率及制造成本的控制等。离散制造业通常需要品类、属性繁多的原材料和配套件&#xff0c;而各类物料的及时供应十分重要&#xff1b;…

优思学院|QCC 是什么意思?有什么用?

QCC 的中文意思是质量控制圈&#xff0c;也有人称为品质圈。 质量控制圈&#xff08;QCC&#xff09;是来自日本的一种质量管理方法&#xff0c;这个概念的作者是石川馨、日本科学家和工程师联盟&#xff08;JUSE&#xff09;共同发明。 QCC的方法是建立由5-11名成员组成的小团…

【VUE2-01】vue2的起步

文章目录一、初识vue1.1vue.js的特点1.2什么是虚拟的dom&#xff1f;1.3为什么使用虚拟的dom1.4vue设计思想二、第一个vue应用如果想系统细致的学习&#xff0c;建议阅读vue的官方网站目前vue官网默认的是vue3的内容&#xff0c;此篇以vue2为基础开始学习一、初识vue 1.1vue.j…

电脑重装系统后没声解决步骤

电脑重装系统之后&#xff0c;发现声音功能&#xff0c;不能正常使用了。对于电脑小白来说&#xff0c;不知道该如何处理&#xff0c;下面就和大家说说重装系统后没声音怎么办呢?&#xff0c;其实完全可以自己处理这种情况&#xff0c;快来看看小白重装系统后没声解决方法吧! …

插入损耗——线对上的信号衰减

“您好&#xff0c;我需要您的帮助。我在测试长距离线缆的时候&#xff0c;插入损耗没有通过测试&#xff01;”这是在对铜缆布线进行验收测量时&#xff0c;我们经常能够听到的问题。针对这一情况&#xff0c;为了能提供更专业的支持&#xff0c;我们必须了解这一电气特性的基…

如何修改linux下的vim复制行数限制

vim-如何修改linux下的vim复制行数限制来自北方的小强正在努力成为资深数字IC搬砖工的搬砖工个人根目录下的.vimrc (~/.vimrc)添加如下内容:set viminfo1000,<600linux下&#xff0c;默认最多复制50行&#xff0c;上述修改即将限制改为600行。注意&#xff1a;1 如果.vimrc文…

Arduino固件库的离线安装方式

参考&#xff1a;https://www.cnblogs.com/hilary0614/p/libraries.html https://jingyan.baidu.com/article/9f7e7ec09d90906f281554e1.html&#xff0c;开发板管理器和管理库区别 Arduino 经常推出新的控制器&#xff0c;这些新的控制器可能不在现有的板子型号中&#xff0c;…

【Linux】Linux 项目自动化构建工具 -- make/makefile

&#x1f451;作者主页&#xff1a;进击的安度因 &#x1f3e0;学习社区&#xff1a;进击的安度因&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;Linux 文章目录一、前言二、概念三、demo 实现四、原理与规则1、依赖关系和依赖方法① 感性理解② 深层理解…

回顾 2022

前言回顾过去的 2022 年&#xff0c;感觉自己学习了不少&#xff0c;输出的不多。适合 Golang 新手入门的项目 go-gin-api[1]&#xff0c;今年基本没更新&#xff0c;目前已收到 4.1k star&#xff0c;感谢大家的认可。关于健康今年室外跑步&#xff0c;跑了有 175 km&#xff…

什么蓝牙耳机音质好?发烧友力荐四款好音质蓝牙耳机

随着蓝牙技术的发展&#xff0c;现如今蓝牙耳机的音质越来越可以与有线耳机的音质相媲美了。音质作为选择蓝牙耳机的重要参考因素之一&#xff0c;在我们的日常生活中&#xff0c;不管是听歌、追剧、通话等&#xff0c;音质不一的蓝牙耳机都能带来不一样的听觉体验。下面&#…

提高1--数字三角形模型

1.摘花生 Hello Kitty想摘点花生送给她喜欢的米老鼠。 她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来。 地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经过一株花生苗就能摘走该它上面所有的花生。 Hello Kitty只能向东或向南走,不…

Java基础知识复习

文章目录复习1. Java编译和运行2. Java运行环境3. Java注释4. Java中的打印5. 数据类型整形浮点型字符类型字节类型布尔类型数据类型转换强制类型转换隐式类型转换小结6. 变量命名规范7. 运算符算数运算符逻辑运算符移位运算符关系运算符8. switch9. 方法方法的重载可变参数变程…

http请求走私详解

前言 HTTP请求走私是一种干扰网站正常处理从一个或多个用户收到的HTTP请求的方法&#xff0c;请求走私漏洞在本质上通常很关键&#xff0c;允许攻击者绕过安全控制&#xff0c;获得对敏感数据的未授权访问&#xff0c;并直接危害其他应用程序的用户。 随便提一句&#xff1a;…

关系抽取概念及相关论文解读

1.信息抽取概述 信息抽取是构建知识图谱的必要条件。知识图谱中以&#xff08;subject&#xff0c;relation&#xff0c;object&#xff09;三元组的形式表示数据。信息抽取分为两大部分&#xff0c;一部分是命名实体识别&#xff0c;识别出文本中的实体&#xff0c;另外就是关…

【dp】排列问题——零钱兑换和组合总和IV

文章目录零钱兑换组合总和IV零钱兑换 很明显&#xff0c;本题使用完全背包算法&#xff0c;求解的是组合数&#xff0c;直接使用完全背包算法即可&#xff0c;为什么是组合数呢&#xff1f; 如果题目说 amount5&#xff0c;coins[1,2,5] 有9种方法&#xff0c;那就是排列数&am…

探秘SSD磨损均衡和闪存管理

一块2TB的SSD要进行3000PE耐久度测试&#xff0c;需要在顺序写入方式下&#xff08;写入放大比接近1&#xff09;写入2TB x 30006000TB的数据&#xff0c;这需要相当长的时间才能完成。有朋友可能会问&#xff1a;在SSD里划分一个1GB容量的小分区&#xff0c;往里面覆盖写入300…

2022年总结:责任驱动开源

文章目录概览阅读2022阅读清单2023 阅读目标文章2022文章列表2023 目标社区WeDataSpherecube-studio &#xff08;aiops平台&#xff09;社区展望小结概览 2022年一年过去&#xff0c;在此总结过往&#xff0c;展望未来&#xff0c;每年都写总结&#xff0c;我希望继往开来&am…

STC单片机基于Keil平台在线调试仿真

STC单片机基于Keil平台在线调试仿真⚡目前STC32G12K128型号的单片机仅支持需要通过SWD接口&#xff08;STC-USB LINK 1D&#xff09;进行调试&#xff0c;STC8H系列可以通过HID接口或者串口进行调试&#xff0c;其他不带HID功能型号的只能通过串口进行调试。 ✨初次调试&#x…

RHCE——编写playbook ansible

1.按照要求定义以下变量。&#xff08;可以在多个位置下定义实现相应操作即可&#xff09; | 变量名 | 值 | | --------- | ------- | | file_name | newfile | | user_name | devops | | pk_name | httpd | 2.编写任务模块在node1和node2主机中根据以上变量值创建对应文本文件…