Java之线程同步、synchronized用法及原理

线程的同步

场景1:两个线程同时访问一个变量,一个线程自增,一个线程自减

public class thread11 {public static void main(String[] args) throws InterruptedException {Thread thread1 = new AddThread();Thread thread2 = new DecThread();// 启动线程thread1.start();thread2.start();// 线程插队thread1.join();thread2.join();System.out.println(Counter.count);}
}class Counter {public static int count = 0;
}class AddThread extends Thread {public void run() {for (int i = 0; i < 10000; i++) {Counter.count = Counter.count + 1;}}
}class DecThread extends Thread {public void run() {for (int i = 0; i < 10000; i++) {Counter.count = Counter.count - 1;}}
}

自增线程和自减线程都执行了一万次,结果本应该为0(不变),但是因为线程不安全,结果并不是0;原因如下:

在这里插入图片描述

线程一和线程二并发执行,线程一执行一次数字本应变为101,此时线程二执行,但在线程一的ILOADIADD之间读取到变量值为100,造成了不同步的问题;保证此过程的原子性,即可解决该问题,如下:

在这里插入图片描述

每次线程执行之前加锁,线程执行之后释放锁;线程一拿到锁,线程二想要执行就必须要等线程一释放锁

public class thread11 {public static void main(String[] args) throws InterruptedException {Thread thread1 = new AddThread();Thread thread2 = new DecThread();// 启动线程thread1.start();thread2.start();// 线程插队thread1.join();thread2.join();System.out.println(Counter.count);}
}class Counter {public static int count = 0;// 创建锁public final static Object LOCK = new Object();
}class AddThread extends Thread {public void run() {for (int i = 0; i < 10000; i++) {synchronized (Counter.LOCK) {Counter.count = Counter.count + 1;}}}
}class DecThread extends Thread {public void run() {for (int i = 0; i < 10000; i++) {synchronized (Counter.LOCK) {Counter.count = Counter.count - 1;}}}
}

使用synchronized关键字修饰代码块,使其线程安全

线程同步锁

  • synchronized用法

    • 修饰代码块

      synchronized:修饰代码块,则其用的锁是某个指定的Java对象

      public static void dosth1() {// 使用当前类Class对象,作为锁对象synchronized (Example2.class) {System.out.println("xxx");}
      }
      
    • 修饰实例方法

      synchronized修饰实例方法,则其用的锁默认 为this当前方法调用对象

      // 方法声明中直接使用synchronized关键字(作用等同于使用this作为锁)
      public synchronized void dosht2() {System.out.println("...");
      }
      
    • 修饰静态方法

      synchronized修饰实例方法,则其用的锁默认 为Class对象

      // 静态方法:方法声明中直接使用synchronized关键字(作用等同于使用this作为锁)
      public synchronized static void dosth2() {System.out.println("xxx");
      }
      
  • synchronized原理

    • 通过monitorenter/monitorexit指令实现监视器机制。

    • 监视器(monitor)获取步骤

      1. 执行monitor指令,判断当前monitor监视器的线程进入数量:如果为0,则该线程直接进入监视器owner,代表该线程拥有监视器,同时进入数设置为1;
      2. 如果线程已经拥有该monitor监视器,重新进入,则进入数+1;如果其它线程尝试获取监视器,则进入阻塞区,线程进入阻塞状态,直到监视器的进入数为0;
      3. 执行monitorexit指令,进入数-1

    在这里插入图片描述

  • 锁升级(锁膨胀)

    • 偏向(斜)锁
      • 只有一个线程执行的场景,使用偏向锁;
    • 轻量级锁
      • 发现多个线程执行的场景,偏向锁升级为轻量级锁;
      • 轻量级锁不能处理并发;
    • 重量级锁
      • 发现多个线程并发执行的场景,轻量级锁升级为重量级锁;
      • 重量级锁通过操作系统的“互斥锁”实现。互斥锁实现线程之间的切换,需要从“用户态”切换到“内核态”,付出高昂的代价,会导致性能下降。

线程同步时的通信

  1. wait():必须通过notify() / notifyAll()唤醒线程
  2. **wait(等待时间):**达到计时时间后,自动唤醒

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

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

相关文章

如何开发通过蓝牙技术实现灯光智能调节的小程序

近年来&#xff0c;随着智能家居市场日渐兴起&#xff0c;人们对于家居生活品质的需求不断提升。在这一背景下&#xff0c;蓝牙智能调节小程序的开发能够为客户提供更便捷、智能化的LED灯光调节方案。需求方想要实现通过蓝牙开发实现LED灯光亮度和颜色的智能调节&#xff0c;同…

DAY29--learning English

一、积累 1.sign up for 2.business trip 3.calendar 4.acne 5.band-aid 6.scar 7.prescription 8.pimple 9.saucy 10.slurp 11.germaphobe 12.shred 13.boggle 14.platser 15.lick 16.sling 17.smack 18.stereotype 19.salmon 20.cable 二、练习 1.牛津原译 calendar. /ˈk…

Windows中的Git Bash运行conda命令:未找到命令的错误(已解决)

在windows中的Gitbash中 打开激活conda环境&#xff0c;并运行&#xff08;前提是你先安装好git&#xff08;自己去官网下载&#xff09;&#xff09;。 要能够在Gitbash上运行Conda&#xff0c; 临时配置 如果你只是临时用一下&#xff0c;就是临时爽一把&#xff0c;那就按…

线程池(ThreadPoolExecutor,as_completed)和scrapy框架初步构建——学习笔记

用法1&#xff1a;map函数 with ThreadPoolExecutor() as pool: results pool.map(craw,utls)for result in results:print(result) 1.Scrapy框架&#xff1a; 五大结构&#xff1a;引擎&#xff0c;下载器&#xff0c;爬虫&#xff0c;调度器&#xff0c;管道&#x…

【vue】provide/inject

provide/ inject这对选项需要一起使用&#xff0c;以允许一个祖先组件向其所有子孙后代注入一个依赖&#xff0c;不论组件层次有多深&#xff0c;并在起上下游关系成立的时间里始终生效。 通途点来讲可以用来实现隔代传值&#xff0c;传统的props只能父传子&#xff0c;而 prov…

1.QT简介(介绍、安装,项目创建等)

1. QT介绍 Qt&#xff08;官方发音 [kju:t]&#xff09;是一个跨平台的C开发库&#xff0c;主要用来开发图形用户界面&#xff08;Graphical User Interface&#xff0c;GUI&#xff09;程序 Qt 是纯 C 开发的&#xff0c;正常情况下需要先学习C语言、然后在学习C然后才能使用…

Linux--shell编程中内部表和外部表之间的转换

内部表和外部表之间的转换 1、查询表的类型 desc formatted student; Table Type: MANAGED_TABLE 2、修改内部表student为外部表 alter table student set tblproperties(EXTERNALTRUE); 3、查询表的类型 desc formatted student; Table Type: EXT…

Scrapy爬虫开发流程全解析

Scrapy是一个快速、高层次的Web爬取框架&#xff0c;用于抓取网页并从中提取结构化的数据。使用Scrapy&#xff0c;您可以轻松地创建复杂的爬虫&#xff08;spiders&#xff09;&#xff0c;用于广泛的用例。本篇博客将引导您完成Scrapy爬虫的开发流程&#xff0c;并提供代码案…

产品化Chatgpt所面临的五大技术挑战

2022年11月&#xff0c;ChatGPT横扫全球&#xff0c;成为应用人工智能&#xff08;AI&#xff09;领域迄今为止最令人惊叹的“哇&#xff01;”时刻&#xff0c;也是当前科技投资激增的催化剂。2023年11月&#xff0c;首席执行官Sam Altman宣布该产品周用户量达到1亿&#xff0…

神经网络系列---归一化

文章目录 归一化批量归一化预测阶段 测试阶段γ和β&#xff08;注意&#xff09;举例 层归一化前向传播反向传播 归一化 批量归一化 &#xff08;Batch Normalization&#xff09;在训练过程中的数学公式可以概括如下&#xff1a; 给定一个小批量数据 B { x 1 , x 2 , … …

GPT技术在学术研究中的革命性应用:开启论文创作新篇章

在学术界&#xff0c;撰写高质量的论文一直是一个挑战性的任务&#xff0c;它不仅需要深厚的专业知识&#xff0c;还要求良好的文献综述能力、数据分析技巧以及清晰的表达能力。近年来&#xff0c;随着人工智能技术的飞速发展&#xff0c;尤其是生成式预训练变换器&#xff08;…

《隐私计算简易速速上手小册》第8章:隐私计算对机器学习和 AI 的影响(2024 最新版)

文章目录 8.1 机器学习中的隐私问题8.1.1 基础知识8.1.2 主要案例:使用差分隐私的机器学习8.1.3 拓展案例 1:基于隐私的数据聚合8.1.4 拓展案例 2:保护隐私的推荐系统8.2 使用隐私计算加强 AI 安全8.2.1 基础知识8.2.2 主要案例:使用同态加密的数据分析8.2.3 拓展案例 1:安…

134 Linux 系统编程11 ,readlink命令,文件目录rwx权限差异,目录操作函数

一 readlink 命令 前面知道&#xff0c;如果a.soft是一个软链接&#xff0c;我们使用 cat a.soft,会直接查看这个软链接指向的文件 那么我们就是想看这个软链接是啥&#xff0c;可以使用 readlink a.soft 二 获取工作目录 getcwd函数 获取进程当前工作目录 (卷3&#xff0c;标…

简单封装axios

目录 一、代码解读二、整体代码 一、代码解读 import axios from ‘axios’; 创建一个名为 instance 的 Axios 实例&#xff0c;配置默认的请求地址和超时时间 const instance axios.create({baseURL: http://localhost:8085,timeout: 5000, });请求拦截器&#xff0c;用于…

camunda源代码编译运行(一):下载编译camunda源代码

使用camunda开源工作流引擎有多种方式&#xff0c;包括&#xff1a;通过docker运行、使用springboot集成、部署camunda发行包、基于源代码编译运行等多种方式&#xff0c;其中&#xff0c;通过源代码编译集成整合方式&#xff0c;是最复杂的一种方式&#xff0c;文本重点介绍如…

ES坑-创建索引使用_下划线-黑马旅游搜不到

学ES的时候&#xff0c;星级过滤无效 找不到数据。 需要 但是我们在创建的时候使用的是keyword 通过研究发现&#xff0c;我们导入数据的时候应该默认的为starName 我get库时候发现有2个字段 所以通过star_name搜索因为都是空数据搜不到&#xff0c;而starName类型为text所以…

第二十五章 : Springboot使用velocity模板引擎

第二十五章 : Springboot使用velocity模板引擎 前言 本章知识点: Velocity 是什么、Velocity引擎是如何进行模板加载、适用场景有哪些、资源加载器的类型、以及Velocity 在代码生成场景中的应用。 Springboot 版本 2.3.2.RELEASE ,xxl-job-core 2.4.0Velocity 是什么? V…

绘图机器(C 语言)

题目来自于博主算法大师的专栏&#xff1a;最新华为OD机试C卷AB卷OJ&#xff08;CJavaJSPy&#xff09; https://blog.csdn.net/banxia_frontend/category_12225173.html 题目 绘图机器的绘图笔初始位置在原点(0,0) 机器启动后按照以下规则来进行绘制直线 尝试沿着横线坐标正…

专注力训练游戏-第15届蓝桥第4次STEMA测评Scratch真题精选

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第171讲。 第15届蓝桥杯第4次STEMA测评已于2024年1月28日落下帷幕&#xff0c;编程题一共有6题&#xff0c;分别如下&a…

fpga_硬件加速引擎

一 什么是硬件加速引擎 硬件加速引擎&#xff0c;也称硬件加速器&#xff0c;是一种采用专用加速芯片/模块替代cpu完成复杂耗时的大算力操作&#xff0c;其过程不需要或者仅需要少量cpu参与。 二 典型的硬件加速引擎 典型的硬件加速引擎有GPU&#xff0c;DSP&#xff0c;ISP&a…