21.3.3 原子性与易变性 21.3.4 原子类

app编写需要哪种语言 原生App开发:优选Swift(iOS)和Kotlin(Android)。跨平台App开发:优选Flutter(Dart)和React Native(JavaScript)。游戏App开发:优选Unity(C#)和Unreal Engine(C++)。低代码工具:适合简单、快速的App制作。 阅读详情

原子操作是不能被线程集中中断的操作。

原子性可以应用于除long和double之外的素有基本类型,jvm将64位的读取和写入当做两个分离的32位操作来执行,产生一个读取和写入操作中间发生上下文切换,导致不同人物可以看到不正确结果的可能性。

volatile关键字还确保了应用中的可视性,如果将一个域声明为volatile的,那么只要对这个域产生了写操作,所有的读曹组就都可以看到这个修改。如果一个域完全有synchronize方法或语句块来防护,就不必将其设置为volatile。

当一个域的值依赖于它之前的值时,volatile就无法工作了。如果某个域内部受到其他域的值的影响,那么volatile也无法工作,例如Range类的lower和upper边界就必须遵循lower<upper的限制。

使用volatile而不是synchronize的唯一安全的情况是类中只有一个可变的域。

  原子操作,对域中的值的赋值和返回都是原子性的对于c++,但是对于java不是。


如果一个域可能会被多个任务同时访问时,或者这些任务中至少有一个是写入任务,那么久应该将这个域设置为volatile,如果将一个域定义为volatile,那么它就会告诉编译器不要执行任何一次读取和写入操作的优化。

 原子类:

AtomicInteger  AtomicLong AtomicReference



在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉。

Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制。

 

synchronized 

同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用

synchronized 修饰的方法 或者 代码块。

 

volatile

用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。volatile很容易被误用,用来进行原子性操作。

 

下面看一个例子,我们实现一个计数器,每次线程启动的时候,会调用计数器inc方法,对计数器进行加一

 

执行环境——jdk版本:jdk1.6.0_31 ,内存 :3G   cpu:x86 2.4G

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public  class  Counter {
 
     public  static  int  count = 0 ;
 
     public  static  void  inc() {
 
         //这里延迟1毫秒,使得结果明显
         try  {
             Thread.sleep( 1 );
         } catch  (InterruptedException e) {
         }
 
         count++;
     }
 
     public  static  void  main(String[] args) {
 
         //同时启动1000个线程,去进行i++计算,看看实际结果
 
         for  ( int  i = 0 ; i < 1000 ; i++) {
             new  Thread( new  Runnable() {
                 @Override
                 public  void  run() {
                     Counter.inc();
                 }
             }).start();
         }
 
         //这里每次运行的值都有可能不同,可能为1000
         System.out.println( "运行结果:Counter.count="  + Counter.count);
     }
}
1
  
1
运行结果:Counter.count= 995
1
实际运算结果每次可能都不一样,本机的结果为:运行结果:Counter.count= 995 ,可以看出,在多线程的环境下,Counter.count并没有期望结果是 1000
1
  
1
很多人以为,这个是多线程并发问题,只需要在变量count之前加上 volatile 就可以避免这个问题,那我们在修改代码看看,看看结果是不是符合我们的期望
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public  class  Counter {
 
     public  volatile  static  int  count = 0 ;
 
     public  static  void  inc() {
 
         //这里延迟1毫秒,使得结果明显
         try  {
             Thread.sleep( 1 );
         } catch  (InterruptedException e) {
         }
 
         count++;
     }
 
     public  static  void  main(String[] args) {
 
         //同时启动1000个线程,去进行i++计算,看看实际结果
 
         for  ( int  i = 0 ; i < 1000 ; i++) {
             new  Thread( new  Runnable() {
                 @Override
                 public  void  run() {
                     Counter.inc();
                 }
             }).start();
         }
 
         //这里每次运行的值都有可能不同,可能为1000
         System.out.println( "运行结果:Counter.count="  + Counter.count);
     }
}

运行结果:Counter.count=992

运行结果还是没有我们期望的1000,下面我们分析一下原因

 

在 java 垃圾回收整理一文中,描述了jvm运行时刻内存的分配。其中有一个内存区域是jvm虚拟机栈,每一个线程运行时都有一个线程栈,

线程栈保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存

变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,

在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。下面一幅图

描述这写交互

 

java volatile1

 

 

read and load 从主存复制变量到当前工作内存
use and assign  执行代码,改变共享变量值 
store and write 用工作内存数据刷新主存相关内容

其中use and assign 可以多次出现

但是这一些操作并不是原子性,也就是 在read load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,所以计算出来的结果会和预期不一样

对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的

例如假如线程1,线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值

在线程1堆count进行修改之后,会write到主内存中,主内存中的count变量就会变为6

线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6

导致两个线程及时用volatile关键字修改之后,还是会存在并发的情况。

<p http:="" www.cnblogs.com="" aigongsi="" "="" target="_blank" style="margin-top: 12px; margin-bottom: 0px; padding: 10px; border: 1px dashed rgb(224, 224, 224); background: rgb(230, 230, 230);">GodIsCoder 
博客园blog地址: http://www.cnblogs.com/aigongsi/ 
独立Blog:  God Is Coder 
个人网站:  iphone发码网 
本人版权归作者和博客园所有,欢迎转载,转载请注明出处

1、Ovirt 开源虚拟化平台安装 Ovirt虚拟化Node和Engine安装 阅读详情

相关推荐

R语言实战:Scheirer–Ray–Hare检验在非正态重复测量数据分析中的应用

本文详细介绍了当重复测量数据不满足正态分布假设时,如何利用R语言中的Scheirer–Ray–Hare检验进行数据分析。该检验作为非参数方法,无需数据服从正态分布或方差齐性,适用于分析组间差异、时间效应及其交互作用。文章通过实战案例,从环境搭建、数据准备、检验执行到结果解读与可视化,提供了完整的操作指南,帮助研究者有效处理心理学、医学等领域的复杂实验数据。

salt9的博客 780

(29)21.3.3 原子性与易变性---Java编程思想之并发笔记

1.原子操作     原子操作时不能被线程机制中断的操作;一旦操作开始,那么一定可以在可能发生的“上下文切换”之前(切换到其它线程执行)执行完毕。     一般情况下不能用原代替同步,除非你是并发专家。否则就是在玩火。     “如果你可以编写用于现代未处理器的高性能JVM,那么就有资格去考虑是否可以避免同步”。     了解原子性是很有用的,原子性可以应用于除long和double之外的

njiang的专栏 1239

即梦 AI 全功能零基础详细教程(纯技术版)

即梦 AI 是一款多模态 AI 生成工具,主打文本生成视频、图片生成视频、角色一致性生成、音画同步等核心功能,依托自研 AI 视觉模型,实现从文本 / 图片 / 音频素材输入,到高清视频、图像内容输出的全流程 AI 创作,支持短视频、短剧、创意素材等多场景创作,具备操作门槛低、生成效率高、画面可控性强的技术特点。@为工具内置引用指令,作用是锁定指定素材 / 角色,强制 AI 按照该素材的核心特征生成内容,无额外付费、解锁要求,免费使用。剧本拆分:将短剧拆分为单镜头(15 秒内 / 个)

2501_92061023的博客 5830

java 多线程 原子性和易变性的理解(还有可视性)

volatile关键字还确保了应用中的可视性。如果你将一个域声明为volatile的,那么只要对这个域产生了写操作,那么所有的读操作就都可以 看到这个修改。即便使用了本地缓存,情况也确实如此,volatile域会立即被写入到主存中,而读取操作就发生在主存中。     理解原子性和易变性是不同的概念这一点很重要。在非volatile域上的原子操作不必刷新到主存中去,因此其他读取该域的任务也不必看

成功需要努力 1312

Zlib1.2.11源码编译(Win10+VS2019)

下载 下载网址: zlib Home Site 得到文件: 解压缩到“D:\SourceCodes\zlib-1.2.11” 使用CMake配置、生成并打开项目 将CMakeLists.txt拖入CMake,配置(Configure): 生成(Generate) 打开项目(Open Project),CMake调用VS2019打开项目 生成debug版本 构建项目ALL_BUILD。成功生成debug版本 在“D:\Sourc...

Alexabc3000的专栏 1893

深入解析SSD报错“READ FPDMA QUEUED”:从诊断到修复全流程

本文深入解析了SSD报错“READ FPDMA QUEUED”的含义、成因与全流程解决方案。该错误通常指示硬盘硬件或健康状态问题。文章详细介绍了如何通过系统日志定位错误、解读关键的S.M.A.R.T.健康报告(重点关注重分配扇区计数等指标),并逐步进行硬件排查(如更换SATA数据线)、软件修复与数据抢救,最终指导用户根据诊断结果做出维修或更换SSD的决策。

weixin_29233333的博客 398

Java原子类Atomic原理和应用

jdk所提供的原子类可以大致分为四种类型: 原子更新基本数据类型 原子更新数组类型 原子更新抽象数据类型 原子更新字段   先来看看jdk提供的原子类(rt.jar包下java.util.concurrent.atomic):   首先我们来写一个数字自增生成器 package cn.itcats.thread.safe.Test1; public class Sequen...

zp的博客 5895

AI视频生成模型训练:从数据准备到部署全流程

咱们这次的目的就像是要建造一座超级厉害的AI视频生成魔法城堡。范围呢,就是从收集建造城堡的材料(数据准备)开始,到把城堡搭建起来(模型训练),再到让城堡能供大家使用(模型部署),涵盖了整个过程的方方面面。接下来我们会先给大家介绍一些重要的术语,就像认识冒险途中的关键道具一样。然后引入一个有趣的故事,带大家进入AI视频生成的奇妙世界,解释核心概念以及它们之间的关系。接着会详细讲解核心算法原理、数学模型和公式,还会有项目实战,带大家亲自体验代码的魅力。

小白菜的博客 399

java 并发原子性与易变性 来自thinking in java4 21.3.3

java 并发原子性与易变性 详细介绍请参阅thinking in java4 21.3.3 thinking in java 4免费下载:http://download.csdn.net/detail/liangrui1988/7580155

偏执狂才能生存!热忱比专业知识更重要......... 1607

YOLOv11 快速入门指南 | 10分钟吃透网络结构与新特性

2024 年 9 月 30 日,Ultralytics 发布了 YOLOv11,这是继 YOLOv8、v9、v10 之后的最新一代实时目标检测模型。 与前几代相比,YOLOv11 在保持“单阶段、实时、端到端”三大基因的同时,带来了两大核心升级:一句话总结:YOLOv11 = 更快 + 更准 + 更少参数。 2.2 微观单元:C3k2 与 C2PSA 2.2.1 C3k2 模块 作用:替换 YOLOv8 的 C2f,做跨阶段局部特征融合。 核心代码(ultralytics/nn/modules/block

shrgegrb的博客 1407

【android bluetooth 案例分析 01】【HiCar 详解 3】【hicar时如何交换Wifi参数的】

如果直接使用 L2CAP(不经过 RFCOMM),会需要额外的协议来保证可靠性,而 RFCOMM 天然支持。BLE 广播的数据长度受限(31 字节 / 255 字节扩展),不适合传输复杂的 Wi-Fi 连接参数。使用 RFCOMM 传输参数,可以兼容不同厂商的车机和手机,而无需依赖特殊的蓝牙功能。手机解析这些参数,并使用 Wi-Fi Direct 连接到车机。,然后才能让 Wi-Fi Direct 进行真正的数据传输。,适合传输 Wi-Fi 连接参数等关键数据。,可以安全地交换 Wi-Fi 连接信息。

奔跑吧 android 的博客 1740

Thinking In Java 学习笔记 21.并发

线程优先级 进程与线程后台(daemon)线程main()是非后台线程在每个线程对象上附着一个异常处理器捕获异常Thread.UncaughtExceptionHandler共享资源竞争互斥量 mutexvolatile关键字保证域可见性,当类中只有一个可变的域时,volatile是安全的使用synchronized关键字使用显示的Lock对象原子性与易变性临界区:...

越努力, 466

【机器学习-09】特征工程

特征工程是机器学习模型构建的初步工作,但它的重要性却贯穿整个模型生命周期。在进行特征工程时,我们需要充分利用数据科学的知识和技巧,结合具体的应用场景和业务需求,来制定出最合适的特征提取和转换策略。只有这样,我们才能为机器学习模型提供最有价值的输入,从而使其发挥出最大的潜力。总之,特征工程是机器学习中的一项关键任务,它需要我们用心去探索、去实践、去创新。只有不断地优化和完善特征工程的过程,我们才能构建出更加准确、更加可靠的机器学习模型,为实际应用带来更大的价值。

qq_38614074的博客 2万+

Java并发笔记(未完待续)

为什么80%的码农都做不了架构师?>>> ...

weixin_33711647的博客 142

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

并发(3)共享受限资源

共享受限资源

SJZYLC的专栏 378

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Java 并发 随笔 1-初尝并发

0. 感觉最近有点犯难了… 《Thinking in java 4th》第21章 并发 并发看起来充满了危险,如果你对它有些畏惧,这可能是件好事… 1. 并发的多面性 作者在“性能优化”和“设计可管理性”的角度上的讨论让人印象深刻(Atom类、显式锁…) cpu 更好的利用多核处理器,同样也提升了单核处理器的程序性能 单核处理器上运行并发程序,会带来额外的上下文切换的代价 考虑阻塞的存在,单核处理器此时可以“腾出手来”,去做其他的事情,保证了程序一定的可响应性 并发显著提升单核处理器的程序性能的案例,即

hyoka的博客 550

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

《JAVA编程思想》学习笔记:第21章(并发)

目录Java编程思想(一)第1~4章:概述Java编程思想(二)第5章:初始化和清理Java编程思想(三)第6章:访问权限Java编程思想(四)第7章:复用类Java编程思想(五)第8章:多态Java编程思想(六)第9章:接口Java编程思想(七)第10章:内部类Java编程思想(八)第11章:持有对象Java编程思想(九)第12章:异常Java编程思想(十)第13章:字符串Java编程思想(十一...

caobaokang的专栏 1569

java编程思想并发

java编程思想并发21.1.2java线程作用21.2基本的线程机制21.2.1使用线程的编写方式21.2.3执行器——Executor21.2.6优先级21.2.9编码的变体,可以有5种内部类写法隐藏线程代码21.2.10任务和线程21.2.11 加入线程21.2.14 捕获异常21.3共享受限资源对象锁——synchronized进入阻塞有如下原因两种不能中断阻塞的情况21.5.3生成者与消...

XiaoMing学习分享博文 326

Thking in java(第四版)-查缺补漏(第21章)

背景 憋了这么久终于可以学到并发了,其实并发很迷人又让人头疼的地方就是如何决解多个线程访问同一个资源而带来的 线程间互相干扰的问题。 1.并发的多面性 并发是用于多处理器编程的基本工具,用并发解决的问题可以分为“速度”和“设计可管理性”。 (1)速度的提高是以多核处理器的形式而不是更快的芯片形式出现的。但是,并发通常是提高运行在单处理器上的程序的 性能,原因如下所述: 如果程序中的某...

DeepingC 278

Java线程安全实战:从i++竞态到Atomic无锁设计

线程安全是Java并发编程的核心基础,本质是解决多线程环境下共享变量的可见性、原子性与有序性问题。其底层依托Java内存模型(JMM)规范,通过synchronized提供互斥与可见性保障,volatile确保变量修改对所有线程即时可见但不保证原子性,而Atomic类则基于CAS指令实现无锁化原子操作。这些机制共同支撑高并发场景下的数据一致性,广泛应用于计数器、状态标志、限流器、配置管理等典型业务模块。理解它们的原理差异与适用边界,是构建可靠电商、金融及实时系统的关键工程能力。

weixin_33834628的博客 375

第21章并发--java编程思想中文第四版-备忘笔记

博学,审问、慎思、明辨、笃行 读实用书时要提出的四个问题: (1)整体来说,这本书到底在谈些什么?big what? 并没有改变多少。 (2)作者细部说了什么,怎么说的? small what? how? (3)这本书说得有道理吗? 是全部有道理,还是部分有道理?why? 作者最终的目标,加上他建议的达成目标的方法-...

weixin_30569033的博客 112

【23种设计模式之】3.单例模式——概述及比较

参考文章:23种设计模式全解析,单例模式的八种写法比较 1. 全局字段初始化 ``` public class Singleton { private final static Singleton INSTANCE = new Singleton(); private Singleton(){} public static Singleton getInstance(...

学习中 174

《Java编程思想》第二十一章 并发(一)

前言: 本系列是我本人阅读java编程思想这本书的读书笔记,主要阅读第五章到第十七章以及第二十一章的内容,今天的笔记是第二十一章 到目前为止,本书所讲到的知识都是有关于顺序编程的,也就是程序在任意时刻只执行一个步骤。但是,在很多情况下,能够并行的运行一个程序中的多个部分,则会变得非常方便和必要。 1. 并发的多面性 并发是指在某个时间段内,多任务交替的执行任务。当有多个线程在操作时,把CP...

wangjimmy1994的博客 436

以libevent网络库为引:网络通信和多线程

1. windows下编译及使用libevent  http://www.cnblogs.com/luxiaoxun/p/3603399.html 2.  &lt;&lt;libevent学习资料&gt;&gt; http://blog.csdn.net/tge7618291/article/details/7698813 3. 源代码编译安装Memcache及libevent库依赖性的解决实...

weixin_34159110的博客 163

Java题库

1.join等待其他的完成后执行 2.exceptionstatemoniter不是当前线程的持有对象 3.illegalThreadStateException:运行的时候发现在循环第二遍的时候出现了java.lang.IllegalThreadStateException异常 通过上网查询发现同一个Thread不能重复调用start方法,做如下修改就好了: 将自己定义的HubRobot

CodeMyDream的专栏 1746

java题库8

1. 一个没有实现Serializable接口的父类,编写一个能够序列化的子类 ,只要父类实现了序列化的接口,或者,子类实现了序列化的接口就可以序列化 “transient”——“瞬态”,先不说这个翻译是否恰当,这个变量关键字一直不曾使用,简单的说就是被瞬态定义的变量不可序列号。或者这么给他换个名字——“不可序列化状态”。 打个比方,如果一个用户有一些敏感信息(譬如密码,银行卡号等),为了安

CodeMyDream的专栏 924
上一篇: 21.3 共享受限的资源
下一篇: 5.5.3 per-connection time zone support
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值