2019独角兽企业重金招聘Python工程师标准>>>

volatile关键字,在我之前的博客 Volatile - 用途 中已经简单讲解过,当时提出了volatile在多线程中是不安全的。本文将重点介绍一种使用方式,可以实现线程安全。

首先,来看一段不安全的示例:

@NotThreadSafepublic class UnsafeCachingFactorizer implements Servlet {private final AtomicReference<BigInteger> lastNumber = new AtomicReference();private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference();public void service(ServletRequest req, ServletResponse resp){BigInteger i = extractFromRequest(req);if (i.equals(lastNumber.get())){encodeIntoResponse(resp, lastFactors.get());} else {BigInteger[] factors = factor(i);lastNumber.set(i);lastFactors.set(factors);encodeIntoResponse(resp, factors);}}
}

上面的示例中,尽管lastNumber和lastFactors这些原子引用本身是安全的,但是无法保证lastFactors中缓存的因数之积等于在lastNumber中缓存的值。也就是说,lastNumber和lastFactors无法保证同一时间只有一个线程修改、无法同时更新,存在竞态条件。


针对上面的竞态条件,提出了一种修复方式:volatile - 可以考虑创建一个不可变的类来包含这些需要原子方式执行的操作数据。看代码:

@Immutable
class OneValueCache {private final BigInteger lastNumber;private final BigInteger[] lastFactors;public OneValueCache(BigInteger i, BigInteger[] factors) {lastNumber = i;lastFactors = Arrays.copyof(factors, factors.length);}public BigInteger[] getFactors(BigInteger i) {if (lastNumber == null || !lastNumber.equals(i)) {return null;} else {return Arrays.copyof(lastFactors, lastFactors.length);}}
}
@ThreadSafepublic class VolatileCachedFactorizer implements Servlet {private Volatile OneValueCache cache = new OneValueCache(null, null);public void service(ServletRequest req, ServletResponse resp){BigInteger i = extractFromRequest(req);BigInteger[] factors = cache.getFactors(i);if (factors == null){factors = factor(i);cache = new OneValueCache(i, factors);}encodeIntoResponse(resp, factors);}
}

对于在访问和更新多个相关变量时出现的竞态条件问题,可以通过将这些变量全部保存在一个不可变对象中来消除。如果是一个可变的对象,那必须使用锁来确保原子性。如果要更新这些变量,那么可以创建一个新的容器对象。

此处,OneValueCache是不可变的,并且在每条相应的代码路径中只会访问一次。通过使用包含多个状态变量的容器对象来维持不变性条件,并且使用一个volatile类型的引用来确保可见性,从而保证了线程安全。

转载于:https://my.oschina.net/xiaowangqiongyou/blog/1922840

volatile - 如何实现线程安全相关推荐

  1. 为什么不使用volatile,其它线程也能得到当前线程修改后的值,不使用volatile也不存在可见性问题?原来解决可见性问题不一定需要volatile,println也可以

    1. 为什么不使用volatile,其它线程也能得到变量修改后的值 实验代码分析: ①初始变量a=true,b=false: ②一个线程判断a或者b是否被改为相应逻辑,如果是,那么输出信息. ③修改a ...

  2. volatile不能保证线程安全

    对于volatile这个关键字,相信很多朋友都听说过,甚至使用过,这个关键字虽然字面上理解起来比较简单,但是要用好起来却不是一件容易的事. 这篇文章将从多个方面来讲解volatile,让你对它更加理解 ...

  3. Volatile关键字与线程安全

    Volatile关键字与线程安全 volatile关键字,它的语义有二: 1.volatile修饰的变量对于其他线程具有立即可见性 即被volatile修饰的变量值发生变化时,其他线程可以立马感知.而 ...

  4. 面试:从volatile说到i++的线程安全问题

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者|ZimZz 来源|https://www.cnbl ...

  5. 【Java 并发编程】线程指令重排序问题 ( 指令重排序规范 | volatile 关键字禁止指令重排序 )

    文章目录 总结 一.指令重排序规范 二.指令重排序示例 总结 Java 并发的 333 特性 : 原子性 : 每个操作都是 不可拆分的原子操作 ; 在线程中进行 a++ 就不是原子操作 , 该操作分为 ...

  6. 并发编程-06线程安全性之可见性 (synchronized + volatile)

    文章目录 线程安全性文章索引 脑图 可见性定义 导致不可见的原因 可见性 -synchronized (既保证原子性又保证可见性) 可见性 - volatile(但不保证操作的原子性) volatil ...

  7. 从volatile说到i++的线程安全问题

    点击上方 好好学java ,选择 星标 公众号 重磅资讯,干货,第一时间送达 今日推荐:分享一套基于SpringBoot和Vue的企业级中后台开源项目,这个项目有点哇塞!个人原创100W +访问量博客 ...

  8. 从 volatile 说到 i++ 的线程安全问题

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达今日推荐:2020年7月程序员工资统计,平均14357元,又跌了,扎心个人原创100W+访问量博客:点击前往,查看更多 来源 ...

  9. java(线程特性,Volatile作用,java内存模型)

    1.java线程特性   1.原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行 银行转账,自己转100给别人,自己账户少100 别人多100 不会出现,自己 ...

最新文章

  1. 少侠,找个千手观音来帮你营销可好?
  2. QQ提示应用程序并行配置不正确,绿色版QQ不能运行解决方法
  3. SAP推出iPhone手机端企业智能管理应用
  4. Junit 测试之 Spring Test
  5. iptables的配置实例
  6. [转]redis 5.0.5 5分钟搭建redis集群
  7. navicat 官方使用手册,中文版,快捷键大全
  8. typechoSQLIte转MySQL_Typecho SQLite与MySQL的数据库切换及解决MySQL连接打开缓慢问题
  9. php oracle 存储过程 返回值,PHP 调用 Oracle 存储过程 之 查询
  10. 联想数据中心技术总监单奖定:双态IT -数字化转型下的IT建设新思路
  11. ★另人无比怀念的90年代动画片★ ‖最终整理篇‖
  12. 射影几何----极点极线割线共点四点调和定理
  13. python javascript人工智能_Python,Java和JavaScript哪个编程语言未来发展空间更大?...
  14. C. Dima and Staircase(思维)
  15. 计算机下桌面显示不出来,电脑桌面文档不会在右边显示出来怎么办
  16. 软件工程----UML建模
  17. JS中1900-2100区间内的公历、农历互转的工具类
  18. 【数字工厂】通信设备制造业“数字工厂”解决方案浅析
  19. Python Socket网络编程(一)初识Socket和Socket初步使用
  20. extern C 引起的 error C2059

热门文章

  1. B树,B+树,B-树和B*树
  2. 魔法引用函数magic_quotes_gpc和magic_quotes_runtime的区别和用法
  3. 以太网帧最小字节数以及以太网碰撞
  4. SpringMVC集成Tiles布局引擎框架
  5. PyTorch中nn.Module类中__call__方法介绍
  6. soul一直显示正在登录聊天服务器,soul这个软件,为什么有些人在玩的时间很久以后(两百天以上),就不会再主动和其他人打招呼了?...
  7. vue饼图统计_做可交互的统计图表,这套图形语法不容错过
  8. 未找到beta版怎么解决_刚刚,谷歌正式发布Android 11 Beta版,带来多项重磅更新...
  9. android 自动化web,如何在android上使用selenium或appium自动化Chrome浏览器?
  10. 沙盘正在注销进程start_进程,线程,多线程