并发编程-基础篇

Java并发编程-基础篇 1. JVM与线程安全 可见性:当多个线程对一个线程进行操作的时候,其中一个线程修改了变量的值,而其他的线程并不知道该值已经被修改 可见性-synchronized JMM关于synchronized的两条规定: 1、线程解锁前,必须把共享变量的最新值刷新到主内存 2、线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值(注意:加锁与解锁是同一把锁) 可见性-... 阅读详情

并发编程-基础篇

前言

文档类型

  • 此文档属于参考手册类文档,只供查阅,所以不会涉及详细的过程说明。

参考书籍

  • Java并发编程的艺术(方鹏飞 等著)
  • 实战Java高并发程序实际(葛一鸣 著)

java对象头

对象头的长度

当前对象类型对象头长度
数组3字长
非数组2字长

对象头的存储结构

长度内容说明
1个字长(32bit/64bit)Mark World存储对象的hashCode以及锁的信息
1个字长Class Metedata Address存储对象类型数据的指针
1个字长Array length数组长度(如果对象是数组)

初始MarkWorld

锁状态25bit4bit1bit偏向锁标志位2bit锁标志位
无锁hashCode对象分代年龄001

随着锁标志位变化的MarkWorld

锁状态30bit2bit锁标志位
轻量级锁指向线程栈中锁记录的指针00
锁状态30bit2bit锁标志位
重量级锁指向互斥量(重量级锁)的指针10
锁状态30bit2bit锁标志位
GC标记空11
锁状态23bit2bit1bit偏向锁标志位2bit锁标志位
偏向锁线程IDEpoch101

volatile

  • volatile保证内存的可见性,不能保证一致性
  • 当线程访问到有volatile修饰的变量a时,会将当前线程栈中的a设为无效,将包含变量a的缓存行设置为无效,重新从内存中读取该变量的值
  • 当线程需要修改变量a时,会将变量a的值刷新到主存中,保证其他变量可以看到该线程对这个变量的修改
  • 有线程thread_a和线程thread_b访问同一个变量a时。假设thread_a先访问到变量a时,java规定,根据happenss-before原则,保证线程thread_a对变量a做的操作,一定能被后访问变量a的线程thread_b感知到,就是说线程thread_b能访问到的一定是最新的数据。
  • volatile修饰的变量,禁止对volatile重新排序。加入内存屏障,确保语义的正确。

synchronize

  • synchronize针对对象加锁,具体来说是对类,或者类的实例加锁。
  • 锁的信息保存在对象头中的。

偏向锁

加锁
  • 当线程访问同步块时:在对象头和栈帧中的锁记录里存储锁偏向的线程ID。
  • 以后当该线程进入和退出同步块时,不需要进行CAS操作来加锁和解锁,只是需要简单测试一下对象头的Mark World里是否存储着当前线程的偏向锁。
  • 如果测试成功,则代表当前线程已经获取到了锁。如果测试失败,测试一下MarkWord中偏向的标志是否设为1。
  • 如果设置了偏向锁,则尝试使用CAS将对象头的偏向锁指向当前线程。
偏向锁的撤销

轻量级锁

加锁
  • 线程执行同步块之前,会在当前线程的栈帧中创建用于存储锁记录的空间,并将对象头中的MarkWord复制到锁记录中。这个记录的锁成为Displaced Mark Word。
  • 然后线程尝试使用CAS将对象头的MarkWod替换为指向锁记录的指针。如果成功,当前线程获取锁。如果失败,表示其他线程竞争锁,当前线程尝试自旋来获取锁。
  • 如果自旋失败,则将对象头中的MarkWord中的锁改为重量级锁,线程进入到阻塞队列中。
释放锁
  • 当获得锁的进程退出同步代码块时,用CAS操作比较:

    发现对象头的MarkWord被改变(有锁竞争时,会将锁标志位标记为重量级锁),则释放锁并从阻塞队列中唤醒等待的线程。

    发现对象头中的MarkWord没有改变,则恢复MarkWord为初始状态(其他线程可以获取了)。

重量级锁

经过轻量级锁变化得到的重量级锁。转化为重量级锁的前提是:多个线程存在竞争锁。

锁的比较

锁类型优点缺点适用场景
偏向锁加锁解锁不需要额外消耗,和执行非同步方法差不多如果存在锁竞争,会带来额外锁撤销的消耗只有一个线程访问同步块
轻量级锁竞争的线程不会阻塞,提高了程序的响应速度得不到锁竞争的线程,自旋消耗CPU追求响应时间,同步块执行速度非常快
重量级锁线程不使用自旋,不消耗CPU线程阻塞,响应时间缓慢追求吞吐量,同步块执行速度较长

CAS(Compare And Swap)

  • 原子性

  • CAS是底层提供的一个调用。

  • CAS(expected_a,altered_a)

  • current_a:函数调用时,从内存中读取到的a的值

  • expected_a:调用这个函数时,你认为当前的a的值

  • altered_a:你希望修改后的a的值

如果内存中的a值和你认为的a值一致,即在当前线程对a变量进行修改时,没有其他线程对a进行过修改,当前修改操作成功,返回成功。
IF current_a == expected_a:
	current_a = altered_a 	
	RETURN TRUE
如果值不一致,即当前线程对a变量进行修改时,有其他线程对a变量进行修改过,当前修改操作终止,返回失败。
ELSE
	RETURN FALSE

缺点

ABA问题

两个线程进行同步操作,线程1获取到共享变量V的值为A,然后此时线程2对共享变量V进行操作将它改为B,然后又改为了A,此时线程1进行CAS操作发现V的值还是A,认为这段时间没有线程对V进行操作,然后执行对V的操作。这听上去没有什么问题,然而实际应用中会带来意想不到的问题。

发生原因

这个问题存在的根本原因是CAS只对值进行判断,会丢失某些线程对变量的操作。

场景

以一个简单的促销活动为例,某购物网站举行促销活动,活动规则如下:

只要当前账户余额小于100元的,免费发50元。

  • 假设线程1就是这个发放代金券的线程,线程1取得当前顾客的账户余额值A,

  • 线程2也是一个发放代金券的线程,线程2在此时也取得了这个顾客的账户余额A,发现A<100,然后线程2就执行CAS操作,给当前账户进行加50元操作,此时账户余额为B,B=A+50。

  • 与此同时,顾客在门店进行消费了50元,此时账户余额变为A,

  • 然后线程1进行判断,发现A<100,所以进行CAS操作,比对了一下余额没有发现变化,它认为这段时间没有人带这个余额变量进行操作过,所以执行账户余额就变为A+50。

  • 最后导致网站对顾客多执行了一次发放补助操作。试想如果对每个顾客的余额进行操作都遇到这种情景,那还不亏到哭。

解决

加版本号,对每个变量不仅仅记录他的值,而且记录发生时的版本(比如通过添加一个flag,来标记是否被处理过,或者记录时间等信息),将这两个值作为一个整体,让CAS进行判断。

这样每次比对时不只是比对值,还比对版本号,就不会发生ABA问题了。

典型实现

类似的处理还有数据库中对数据行的操作也可以采用加版本号来解决。

循环时间长开销大

如果循环CAS操作一直不成功,会给CPU带来很大开销。

只能保证一个共享变量的原子操作
解决

将多个共享变量合并成一个共享变量来操作,

典型实现

读写锁中,将读状态和写状态放在一个变量中,低16位表示写状态,高16位表示读状态。

模板匹配加速之金字塔分层搜索 图像金字塔是一种多分辨率图像表示方法,它通过一系列逐渐缩小或放大的图像来表示原始图像的不同尺度。高斯金字塔(Gaussian Pyramid):通过不断下采样(降采样)生成更小的图像。拉普拉斯金字塔(Laplacian Pyramid):通过高斯金字塔和差分操作生成一组残差图像。在模板匹配中,我们主要使用高斯金字塔来实现多尺度匹配。金字塔灰度模板匹配通过多尺度搜索策略,在保持较高准确率的同时显著提升匹配速度,尤其适用于:高分辨率图像处理实时检测系统移动端设备等资源受限场景。 阅读详情

相关推荐

基于知识图谱的旅游推荐系统

这一系统整合了当今先进的数据技术:采集携程等大型平台的景点数据,通过爬虫技术源源不断地获取最新的旅游信息。此外,我们采用Neo4j图数据库来存储和处理这些数据,结合自然语言处理技术,为你提供精准的旅游建议。:通过直观的知识图谱展示,了解各个景点之间微妙的联系,无论是文化背景还是地理方位,你都能从中发现新的旅行灵感。准备毕业设计的同学,关注我们,这是一个集成了多种前沿技术的项目,为你的学术成果锦上添花。:不再浪费时间,系统根据你的偏好和历史评分,利用协同过滤技术推荐适合的旅游目的地。

qalangtao的博客-qalangtao.com 774

学习笔记---锁的膨胀升级

锁的类型存放地 —markWorld markworld 是对象头的一部分,他的主要功能是 存储 gc标志,是否可以偏向,锁的类型,hashcode,分代年龄,以及与锁有关的线程信息,所以要了解所得升级先要了解markWord是什么样的 markworld 以二进制的形式总共的存储64bit HashCode信息 位于markworld的26bit~56bit 在计算过hashcode之后,hashcode信息会记录在markworld上 偏向锁信息 位于markworld的1bit~54bit 在允许偏

qq_34404994的博客 928

NVMe-MI 协议解析:带外管理框架与实现原理

本文深入解析了NVMe-MI协议,这是一种用于NVMe固态硬盘的标准化带外管理接口。文章详细阐述了其独立于操作系统的管理框架,通过MCTP协议栈实现,支持SMBus/I2C、PCIe VDM和I3C等物理层,从而在系统故障时仍能可靠地进行健康监控、固件升级等关键运维操作,是现代数据中心存储管理的核心基础设施。

lll78的博客 962

JVM内存模型中对象的组成结构

JVM内存模型中对象的组成结构 在Java内存中,Java对象由三个部分组成:对象头、实例数据、对齐填充。下面依次来讲下这三个部分。 一、对象头 对象头的组成部分如下图所示: 1、MarkWorld(运行时元数据) (1)哈希值 它是一个地址,用于栈对堆空间中对象的引用指向,不然栈是无法找到堆中对象的 (2)GC分代年龄 记录幸存者区对象被GC之后的年龄age,一般age为15(阈值为15的原因是因为age只有4位最大就可以将阈值设置15)之后下一次GC就会直接进入老年代,要是还没有等到年龄为15,

qq_35843514的博客 792

告别眼疲劳!保姆级教程:给你的SecureCRT v8.7.2换上护眼高亮配色(附透明背景设置)

本文提供了一份详细的SecureCRT v8.7.2护眼高亮配色方案教程,帮助程序员缓解眼疲劳问题。通过科学调整配色方案、动态环境自适应设置以及字体渲染优化,显著提升终端使用的舒适度和工作效率。特别推荐Solarized Dark和One Dark Pro医学适配版配色方案,适合长时间编码工作。

weixin_42549496的博客 356

5、OpenClaw(龙虾助手)飞书机器人完整对接指南(2026最新版)

OpenClaw v2026.2.2+ 版本,防火墙内也能正常工作,是目前最稳定、最简单的企业内部AI助手部署方案。

欢迎光临~知1而N的博客 457

synchronized原理

Java对象头 Java对象由对象头和对象成员组成,存储时为了实现一些额外的功能 设置了对象头。 普通对象 对象头 |--------------------------------------------------------------| | Object Header (64 bits) | |------------------------------------|-------------------------| |

最自由的笑的博客 434

2026零成本私有化:OpenClaw一键搭建Discord/Telegram智能机器人,数据不出本地,永久免费替代ChatGPT

如果内置的功能不能满足你的需求,你可以很容易地添加自己的自定义工具。public string Description => "查询指定城市的天气";// 调用天气API获取天气信息return $"city今天的天气是晴,温度25度";// 注册工具今天北京的天气怎么样?大模型的选择很重要:不要盲目追求大参数的模型。对于大多数场景来说,7B参数的模型已经足够用了,而且速度快,内存占用低。上下文长度不要设置太大:上下文长度越大,内存占用越高,推理速度越慢。

2601_94871597的博客 261

JAVA多线程的初级认识4-锁的基本认识

Java中多线程的技术必然要了解的必然是锁~锁保证多线程的数据安全。所以不多说进入主题。 最轻量级的锁Volatile 当然这是因为它只能修饰变量,而且相对于synchronized关键字轻量了很多~ 对于变量增加了volatile的修饰,表示该数据的写和读都直接同步到主内存,所以保证该变量的任何修改对于其他线程是可见的。 我们可以查看关于修饰volatile变量的编译文件和指令,可以看出~里面会...

comil4444的专栏 289

【Unity-UGUI控件全面解析】| Canvas 画布组件详解

画布 (Canvas) 是应该容纳所有 UI 元素的区域。画布是一种带有画布组件的游戏对象,所有 UI 元素都必须是此类画布的子项。 创建新的 UI 元素(如使用菜单 GameObject > UI > Image 创建图像)时,如果场景中还没有画布,则会自动创建画布。UI 元素将创建为此画布的子项。 画布区域在 Scene 视图中显示为矩形。这样可以轻松定位 UI 元素,而无需始终显示 Game 视图。 画布 使用 EventSystem 对象来协助消息系统。

努力前行,总会成为自己心中的那道光 2万+

华为OD机试真题2025双机位B卷 Java&Go 实现【朋友圈个数】

给定一组朋友关系,统计一下该朋友关系网中的朋友圈个数。 朋友圈的定义:一个朋友圈至少由3个朋友组成,且要求同一个朋友圈中的任意两个人都具有直接的朋友关系。 输入描述 输入一个朋友关系列表,如 Fiends =A.B],[A.C],IB,DI,其中的每一个元素 Friendsi表示 Friends[i][0)和 Friends [i][1] 是朋友关系 先输入一个数字 N 代表关系的总数,后面每条关系一行,两个成员以逗号分隔

MISAYAONE的博客 521

高并发篇_5 Synchronized源码分析II

高并发篇_2 Synchronized源码分析II 田超凡 1 前置准备工作 虚拟机环境搭建和版本检查 本文讲解的主要是站在CPU和JVM字节码角度来分析Synchonized实现原理,具有一定深度,为便于你更好地理解和实操本文所总结的知识点,需要先检查服务器JDK版本,由于不同版本的JVM虚拟机有差异(32bit/64bit),本文以当前主流的64bit HotSpot虚拟机实现来分析Synchronized锁实现原理,在实操环节开始之前,需要先检查服务器JDK版本是否是64bit HotSpot

田宝宝的博客 487

[系统安全] 四十七.恶意软件分析 (3)动态分析经典沙箱Cape的安装和基础用法详解

系统安全将更好地帮助初学者了解病毒逆向分析和系统安全。前文详细介绍恶意代码静态分析经典工具Capa的基础用法,以及批量提取静态特征和ATT&CK技战术,主要是从提取的静态特征Json文件中提取关键特征。这篇文章将详细讲解动态分析沙箱Cape,其是一个开源的自动恶意软件分析系统,通过自动运行和分析恶意软件,全面分析和提取恶意软件的关键特征。本文先介绍Cape沙箱的安装和基础用法,后续随着深入再分享。基础性文章,希望对您有帮助!

杨秀璋的专栏 6739

java并发编程_深入理解java并发编程、并发编程相关概念基础篇

一、前言Come on, let's all come together 不知道各位小伙伴在对于并发编程相关的知识有了解多少呢?无论你是小白还是大牛、我这篇文章希望对你们有所帮助~~~以下是我耗费好几天整理的文章的部分。主要分为俩大部分进行学习:分为基础篇以及进阶篇,下面就开始基础篇的学习。二、并发编程的相关概念2.1.同步(Sync)与异步(Async)2.2.1 同步(Sync)所谓同步,就是...

weixin_29230901的博客 164

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Java并发编程实战(基础篇)

学习本文内容,默认已经了解Java多线程基础。 本篇即为基础篇,那么主要讨论如何编写线程安全的代码,大概分为3个方向 如何避免多线程同时访问同一时刻访问相同数据 共享发布对象,从而使多线程同时安全访问 根据现有线程安全组件构建线程安全的类 在学习各模块只是之前,先普及一些知识。 1.编写线程安全的代码核心? 在访问共享、可变的状态要进行正确的管理。(可能现在还不太明白,看下去慢慢就懂了) 2....

淦淦淦! 1087

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

并发编程学习【基础篇】

由浅入深地学习JUC,一起每天进步一点!

qq_44654974的博客 872

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Go 并发编程之美:基础篇

Go 语言在被设计的时候,Java 和 C++ 是编写服务器程序最常用的语言(至少在 Google 是这样),这是因为使用这些语言可以高效的开发。但是 Go 设计者们觉得像 Java 和 C++ 这些语言需要开发者记忆太多的语法和规则,并且需要重复做的事情太多,这导致一些程序员开始转向更加动态、流畅的语言,如 Python。但是付出的是损失开发效率和对类型安全检查的缺失。Go 设计者们认为应该可以...

GitChat 674

并发编程之基础篇

大家好, 这里是Yve菌. 今天给大家带来一篇并发编程的基础知识, 要想学好并发编程就必须要掌握好以下的知识点!

Limelimelimes的博客 389

【Java】并发编程-多线程基础篇

多线程 一、预热 1、进程VS线程 1)进程 进程是运行着的程序代码。一个进程只能对应一个程序代码,但一个程序代码可以对应多个进程。直白来说,程序代码是菜谱,进程是厨师烹饪的过程。对于同一个菜谱,可以有多个厨师同时按其制膳。 进程是操作系统分配资源的基本单位,进程之间的资源不共享。两个厨师同时在做清蒸鲈鱼,同一条鲈鱼不可同时被二者使用,因为最后做出来的是两盘,不是一盘。 2)线程 线程是进程的一段执行逻辑,一个进程可以由多个线程组成。厨师在制膳过程中,可能一边在一个锅里熬制浇汤,一边在另一个锅里蒸鱼,可能同

weixin_45880263的博客 787

并发编程 · 基础篇 · android线程那些事

小木箱成长营并发编程系列教程(排期中): 并发编程 · 基础篇(下) · android线程池那些事 并发编程 · 提高篇(上) · Java并发关键字那些事 并发编程 · 提高篇(下) · Java锁安全性那些事 并发编程 · 高级篇(上) · Java内存模型那些事 并发编程 · 高级篇(下) · Java并发BATJ面试之谈 并发编程 · 实战篇 · android下载器实现 Tips: 关注微信公众号小木箱成长营,回复 "并发编程" 可免费获得并发编程思维导图 一、序言 Hello,我是小木

Kibaco的博客 713

并发编程基础篇和中级篇

添加链接描述

java技术学习 271

java并发编程:基础篇

2021年第一个安排,搞一波java并发编程的知识。大概会分几篇来展开,本次首先梳理一下线程的基础知识。 1 什么是线程 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。 程序计数器:是一个.

小辙 176

Java并发编程基础篇

的线程的ThreadLocalMap中以该线程为key,赋的值的为值来创建当前线程的对应的HashMap,在Java中,启动main函数时,其实启动的是一个JVM的进程,尔main函数所在的线程是主线程。是进程的一个执行路径,一个进程可以有多个线程,线程之间共享进程的资源。:使用完这些变量后要及时删除,否则可能会造成内存溢出。在线程中对ThreadLocal赋值时,实际上是。是系统分配资源的基本单位,

sss1513的博客 350

并发编程 · 基础篇(下) · 三大分析法分析线程池

如果线程正常退出,判断当前线程数量是否小于线程池最小线程数量,如果小于,直接补齐,否则,直接返回。因此,当暂停线程池的时候,集合中的任务就是正在执行的任务,依次遍历调用任务的 pause 方法,当恢复线程池的时候,依次遍历调用任务的 resume 方法。更新线程池的状态为 TIDYING,调用 terminated(),这是一个 hook 方法,可以在这里面做一些资源回收的操作,执行完后,设置线程池状态为 TERMINATED,唤醒在 awaitTermination 方法上等待的线程。

Kibaco的博客 399

JAVA并发编程(基础篇)

并发编程就是使用编程语言编写一个可以在同一时间段内执行多个任务的程序,这样就能充分利用CPU的多核优势,让程序运行得更快,但是并发编程并不总是能提高程序运行速度的,而且并发编程可能会遇到很多问题,比如并发安全、死锁、内存泄漏、上下文切换等问题,这就需要我们去了解Java并发编程的三大特性,从而更好地解决这些问题。

G_12_M的博客 1227

Java并发编程基础篇(二)——各类锁的使用方法

Java并发编程知识点梳理(一)——并发编程的使用 Java并发编程是深入了解Java的必备知识。本文综合了《Java并发编程之美》、《Java并发编程艺术》等经典书籍,也参考了廖雪峰的Java教程,针对Java并发编程的知识点进行梳理。 不同于Redis系列从底层数据实现到多机数据库再到实操的视角,Java并发系列将会采用自顶向下的视角,先从使用侧角度讲述如何进行并发编程,再探讨并发编程乃至JUC包的底层原理。因为Redis使用起来比较简单,设计也比较简洁;而Java并发光是使用就已经很让人头疼了,一上来

上海大猫集团 283
上一篇: 操作系统的启动与硬盘分区基本知识
下一篇: Maven仓库配置
Coder_Stephen
博客等级 码龄9年 16粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值