热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java线程之同步替代方案CAS

2019独角兽企业重金招聘Python工程师标准1.并发系统的同步机制在设计并发系统的时候,设计同步机制是极为重要的一环。同步机制就是保证状态安全,

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

1.并发系统的同步机制

在设计并发系统的时候,设计同步机制是极为重要的一环。

同步机制就是保证状态安全,保证状态的原子性、可见性和有序性。

最常见的同步机制是使用悲观锁。即使用synchronized、ReentrantLock等工具来实现同步。在这种方案下,如果发生了竞争,一些线程就要被操作系统挂起,在稍后又要恢复运行。操作系统在挂起和恢复线程的过程中存在很大的开销。

与锁相比,volatile是一种更轻量级的同步机制。但是volatile的使用场景局限性很大:它不能用于构建原子的复合操作,就是只能保证一个状态变量同步;它也不能用于新值依赖旧值的情况。

除了这两种情况,还有第三种方案:Compare and Swap,简称CAS。CPU支持很多原子指令,比如:测试并设置(Test-and-Set),获取并递增(Fetch-and-Increment),交换(Swap),比较并交换(Compare-and-Swap)…… CAS正是CPU的一个原子指令。但是,并不是每一种CPU架构都实现了CAS。

CAS包含了3个操作数——需要读写的内存位置V,进行比较的值A和拟写入的新值B。当且仅当V的值等于A时,CAS才会通过原子的方式用新值B来更新V的值。可以把CAS看做一把乐观锁。CAS的典型使用模式是:首先从V中读取值A,并根据A计算新值B,然后再通过CAS以原子方式将V中的值由A变成B。

而且,CAS的性能会随着CPU数量的不同而不同。因为CPU之间要进行同步,所以CPU越多,CAS性能越差。

CAS可能会存在ABA问题,如果V的值首先由A变成B,再由B变成A,这仍然发生了变化,但是可以更新成功。这个问题可以引入版本号来解决:每修改一次,内存的版本号就更新一次,比价的时候带上版本号即可。

当多个线程使用CAS同时更新一组状态变量时,只有一个线程能更新变量的值,而其他线程都将失败。失败的线程不会被挂起,而是返回失败结果,让应用程序开发者处理。开发者可以重试,也可以进行一些恢复操作,也可以直接放弃……这样其实有利有弊:

  • 利:CAS是CPU指令,效率肯定比操作系统层面的锁机制高。然后CAS不需要挂起线程,所以就没有挂起和恢复线程的开销。获取一把无竞争的锁的开销大约是CAS操作的开销的两倍。
  • 弊:竞争失败的善后操作由开发者提供,会增加程序的复杂度;在竞争很激烈的情况下,善后操作会变得很多,直接降低性能。

所以,在竞争程度较高的情况下锁的性能反而可能会更好。而且使用CAS开发的复杂度会比使用锁高很多,建议直接使用由开发专家开发好的基于CAS的并发系统,应用开发者不要随便使用CAS进行开发。

2.Java中用CAS实现的非阻塞算法

从Java 8之后,ConcurrentHashMap、ConcurrentLinkedDeque、ConcurrentLinkedQueue、ConcurrentSkipListMap、ConcurrentSkipListSet内部都使用了CAS实现了非阻塞算法。以ConcurrentHashMap为例,在Java 8之前是使用分段锁的方法实现的并发,Java 8改成了使用CAS。这些类都是由开发专家实现的,我们当然可以放心用,而且性能肯定不错。

3.原子变量类

CAS是CPU指令,所以如果Java平台不做支持,Java开发者是没办法使用CAS的。从Java 5开始,Java平台提供了原子变量类,在int、long和对象的引用等类型上都公开了CAS操作。这样,让我们Java开发者也能一定程度上使用CAS设计并发系统。但是不是所有的CPU都支持CAS指令,这时JVM将使用自旋锁。

共有12个原子变量,可分为4组:标量类、更新器类、数组类以及复合变量类:

  • 标量类:AtomicBoolean、AtomicInteger、AtomicLong。其他基本类型可以先转化成int或long,再使用原子变量类。
  • 更新器类:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater。基于反射对非原子类进行原子更新。
  • 数组类:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray。可以对数组里面的元素进行原子操作。
  • 复合变量:AtomicReference、AtomicMarkableReference、AtomicStampedReference。对普通对象进行原子操作。后面两个可以防止ABA问题。

总结:

  • CAS适合于竞争程度不高的场合(事实上大部分并发系统都是为了实现业务,竞争都不会很高,不会故意引入大量竞争);
  • CAS设计的系统复杂度比锁实现的系统高,所以Java开发者不要使用CAS开发太复杂的并发系统。在 Java平台中很多非阻塞算法都由CAS实现,Java开发者可以直接使用;
  • CAS是CPU指令,Java开发者不能直接使用,可以借助Java平台公开的原子变量类使用。

转:https://my.oschina.net/leaforbook/blog/1827325



推荐阅读
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文介绍了响应式页面的概念和实现方式,包括针对不同终端制作特定页面和制作一个页面适应不同终端的显示。分析了两种实现方式的优缺点,提出了选择方案的建议。同时,对于响应式页面的需求和背景进行了讨论,解释了为什么需要响应式页面。 ... [详细]
author-avatar
mobiledu2502861997
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有