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

news2024/11/20 2:45:20

线程的同步

场景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.coloradmin.cn/o/1469399.html

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

相关文章

编曲学习:高叠和弦 挂留和弦 和弦实战应用

高叠和弦 挂留和弦 和弦实战应用小鹅通-专注内容付费的技术服务商https://app8epdhy0u9502.pc.xiaoe-tech.com/live_pc/l_65d4826fe4b04c10a1310517?course_id=course_2XLKtQnQx9GrQHac7OPmHD9tqbv 七和弦 以三和弦举例,三和弦上面叠一个三度的音,就变成了七和弦。 从下到…

opencv python投影变换效果

变换原理&#xff1a; https://www.cnblogs.com/txwtech/p/18024547 python示范代码&#xff1a; src2原图&#xff0c;4个坐标点 dst2转换后&#xff0c;4个坐标点 p_touyin cv2.getPerspectiveTransform(src2,dst2) #计算投影变换矩阵 #利用矩阵值进行图像投影变换 r…

全流程点云机器学习(二)使用PaddlePaddle进行PointNet的机器学习训练和评估

前言 这不是高支模项目需要嘛&#xff0c;他们用传统算法切那个横杆竖杆流程复杂耗时很长&#xff0c;所以想能不能用机器学习完成这些工作&#xff0c;所以我就来整这个工作了。 基于上文的数据集切分 &#xff0c;现在来对切分好的数据来进行正式的训练。 本系列文章所用的…

【Pytorch深度学习开发实践学习】B站刘二大人课程笔记整理lecture11 Advanced_CNN 实现GoogleNet和ResNet

【Pytorch深度学习开发实践学习】B站刘二大人课程笔记整理lecture11 Advanced_CNN 代码&#xff1a; Pytorch实现GoogleNet import torch from torchvision import datasets, transforms from torch.utils.data import DataLoader import torch.nn as nn import torch.nn.fun…

内核解读之内存管理(8)什么是page cache

文章目录 0. 文件系统的层次结构1.什么是page cache2.感观认识page cache3. Page Cache的优缺点3.1 Page Cache 的优势3.2 Page Cache 的劣势 0. 文件系统的层次结构 在了解page cache之前&#xff0c;我们先看下文件系统的层次结构。 1 VFS 层 VFS &#xff08; Virtual Fi…

【Ubuntu】解决Ubuntu 22.04开机显示器颜色(高对比度/反色)异常的问题

使用Ubuntu 22.04时强制关机了一下&#xff08;make -j16把电脑搞崩了&#xff09;&#xff0c;开机后系统显示的颜色异常&#xff0c;类似高对比度或反色&#xff0c;如下图。看着很难受&#xff0c;字体也没办法辨认。还好之前遇到过类似的问题&#xff0c;应该是一个配置文件…

装修避坑干货|阳台洗衣柜洗衣机一体柜设计。福州中宅装饰,福州装修

装修的时候常常会在洗衣柜中嵌入洗衣机&#xff0c;其实阳台柜的安装并不像看起来的那么简单&#xff0c;下面给大家说说几个注意事项‼️ 01.水电位置 在安装阳台柜之前&#xff0c;务必确认水电管道的位置。确保阳台柜不会阻碍水电管道的使用&#xff0c;以免造成不必要的麻…

Three.js-02Vue框架入手

1.创建项目 说明&#xff1a;默认有vue基础&#xff0c;node版本18以上。 vue create threejs 2.选择vue3 4.安装 npm i three 5. 修改页面 <template> <div></div> </template><script setup> import * as THREE from three;const width win…

查看仓库版本记录

打开命令行窗口 输入git log即可。 若发现分支不对&#xff0c;方法如下 查看项目目录&#xff0c;命令行输入dir可以查看 多个moudel&#xff0c;进入到需要查版本记录的moudel下 命令行输入cd .\文件名如wowo-win-server\ 切换到wowo-win-server文件夹下后&#xff0c;再输入…

【Unity】提示No valid Unity Editor liscense found.Please active your liscense.

有两个软件&#xff0c;如果只有一个&#xff0c;点黑的不会有效果、、、、&#xff08;楼主是这个原因&#xff0c;可以对号入座一下&#xff09; 简而言之&#xff0c;就是去下载Unity Hub&#xff0c;再里面激活管理通行证 问题情境&#xff1a; 点击unity出现以下弹窗&a…

板块一 Servlet编程:第八节 文件上传下载操作 来自【汤米尼克的JavaEE全套教程专栏】

板块一 Servlet编程&#xff1a;第八节 文件的上传下载操作 一、文件上传&#xff08;1&#xff09;前端内容&#xff08;2&#xff09;后端内容 二、文件下载&#xff08;1&#xff09;前端的超链接下载&#xff08;2&#xff09;后端下载 在之前的内容中我们终于结束了Servle…

C++——基础语法(2):函数重载、引用

4. 函数重载 函数重载就是同一个函数名可以重复被定义&#xff0c;即允许定义相同函数名的函数。但是相同名字的函数怎么在使用的时候进行区分呢&#xff1f;所以同一个函数名的函数之间肯定是要存在不同点的&#xff0c;除了函数名外&#xff0c;还有返回类型和参数两部分可以…

【Linux】 faillock 命令使用

faillock 命令 faillock 命令是 PAM (Pluggable Authentication Modules) 的一部分&#xff0c;它被设计用来跟踪失败的登录尝试&#xff0c;并在连续失败尝试超过某个阈值时锁定账户。这个功能可以帮助系统管理员识别和防止暴力破解攻击。当一个用户连续多次输入错误的密码后&…

Vue.js+SpringBoot开发超市商品管理系统

目录 一、摘要1.1 简介1.2 项目录屏 二、研究内容2.1 数据中心模块2.2 超市区域模块2.3 超市货架模块2.4 商品类型模块2.5 商品档案模块 三、系统设计3.1 用例图3.2 时序图3.3 类图3.4 E-R图 四、系统实现4.1 登录4.2 注册4.3 主页4.4 超市区域管理4.5 超市货架管理4.6 商品类型…

Python中的functools模块详解

大家好&#xff0c;我是海鸽。 函数被定义为一段代码&#xff0c;它接受参数&#xff0c;充当输入&#xff0c;执行涉及这些输入的一些处理&#xff0c;并根据处理返回一个值&#xff08;输出&#xff09;。当一个函数将另一个函数作为输入或返回另一个函数作为输出时&#xf…

项目实战:Qt监测操作系统物理网卡通断v1.1.0(支持windows、linux、国产麒麟系统)

若该文为原创文章&#xff0c;转载请注明出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/136276999 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结…

数据结构-列表LinkedList

一,链表的简单的认识. 数组,栈,队列是线性数据结构,但都算不上是动态数据结构,底层都是依托静态数组,但是链表是确实真正意义上的动态数组. 为什么要学习链表? 1,链表时最简单的动态数据结构 2,掌握链表有助于学习更复杂的数据结构,例如,二叉树,trie. 3,学习链表有助于更深入…

fpga_硬件加速引擎

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

【Web】CTFSHOW 常用姿势刷题记录(全)

目录 web801 web802 web803 web804 web805 web806 web807 法一&#xff1a;反弹shell 法二&#xff1a;vps外带 web808 web809 web810 web811 web812 web813 web814 web815 web816 web817 web818 web819 web820 web821 web822 web823 web824 web825…

python统计分析——单因素方差分析

参考资料&#xff1a;用python动手学统计学 方差分析&#xff1a;analysis of variance&#xff0c;缩写为ANOVA 1、背景知识 1.1 要使用方差分析&#xff0c;数据的总体必须服从正态分布&#xff0c;而且各个水平内部的方差必须相等。 1.2 反复检验导致显著性结果更易出现…