多线程之CAS与synchronized的比较

业务场景:需要实现一个支持并发的计数功能

1、计数功能的基本实现是:

public class Increment{private int count = 0;public void add(){  count++;  }}

2、以上实现在并发环境下是不安全的,故修改方案1是加锁synchronized:

public class Increment{private int count = 0;public synchronized void add(){  count++;  }}

//悲观锁,加锁后只能有一个线程你执行++操作,其他线程需要等待

//不会出现count计数不准确的问题,线程安全

3、但是以上实现,会让线程串行化,排队等待获取锁、加锁、处理数据、释放锁,并发下显得不合理

修改方案2是使用Java并发包concurrent下的Atomic原子类

public class Increment{private AtomicInteger count = new AtomicInteger();public synchronized void add(){count.incrementAndGet();}}

//多个线程可以并发的执行AtomicInteger的incrementAndGet()方法,把count的值累加1并返回累加后最新的值

//Atomic原子类底层用的是无锁化的CAS机制,保证多线程修改一个数值的安全性

4、实现原理:

(1)每个线程都会先获取当前的值,接着走一个原子的CAS操作,原子的意思就是这个CAS操作一定是自己完整执行完的,不会被别人打断;

(2)在CAS操作里,比较一下,现在的值跟刚才我获取到的那个值,是否相等,是则说明没有人改过这个值,那么将它设置成累加1之后的一个值;

(3)同理,若有人在执行CAS时,发现自己之前获取的值与当前的值不一样,说明有其他人修改了值,导致CAS失败,失败之后进入一个循环,再次获取值,再执行CAS操作。

5、CAS的问题:

每次去比较的时候,都发现值被别人改了,就会进入无限重复的循环。大量线程高并发时相当于空循环,自旋转,性能和效率都不是特别好。

Java8的新类LongAdder,尝试使用分段CAS以及自动分段迁移的方式来提升多线程高并发执行CAS操作的性能。核心思想是热点分离,类似concurrentHashMap.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555634.shtml

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

相关文章

6 日期字符串转日期_山西省导游协会关于发放电子导游证的通知 (生成日期为2020年5月28日2020年6月3日)...

各位会员、导游同仁们:山西省导游协会电子导游证(生成日期为:2020年5月28日-2020年6月3日)已制作完成,为保障电子导游证发放工作顺利进行,现将发放电子导游证有关事项通知如下:一、领取人员手机A&#xff3…

CAS和Synchronized知识

一. CAS 何为CAS。 CAS(Compare And Swap )是乐观锁的一种实现方式,是一种轻量级锁。JAVA1.5开始引入了CAS,JUC下很多工具类都是基于CAS。 CAS的实现方式 CAS有3个操作数,内存值V,旧的预期值A&#xff0…

自动设置图片的序号_编写学位论文时如何给表格和图片自动编号

引言最近和论文格式的检测系统斗智斗勇,可以说是摸清了系统的脾气并且能够把错误数控制在0。其中,论文正文的表格和图片自动编号的问题还是挺有意思的,特此记录一下。需求对于表格,系统要求表格题注处于表格*上方*,并按…

使用CAS代替synchronized

在开发当中需要经常用到synchronized保证代码线程安全,在竞争条件下会阻塞等待资源,如果允许竞争不到资源返回失败,就可以使用cas减少阻塞时间。先来看一个cas的单例模式。 public class NonBlock {private static volatile NonBlock nonBlo…

uniapp 获取图片的高度_uni-app获取元素高度等信息,并设置元素top信息

本文主要简介uni-app获取元素信息及设置信息等获取元素高度可查看官方文档mounted() {const query uni.createSelectorQuery().in(this);query.select(#editor).boundingClientRect(data > {console.log(data)}).exec();},这里的data用于获取这个元素大小及位置信息&#x…

关于java中线程yield()方法问题

关于java中线程yield()方法问题 问题一: 我知道yield是用来休眠当前线程,但我查看了资料,又说其不会释放锁,所以我就不解了,其明明会将cpu资源给其他线程,那它不释放锁,其他线程有怎么获取cpu资…

Lisp尺寸标注增加前后缀_求一CAD标注加前缀与后缀lisp

回答:1.计算所有线段总长度(加载后只需框选所有线段便可得出这些线段的总长度)(defun c:LL ()(setvar "cmdecho" 1)(setq en (ssget(list (0 . "spline,arc,line,ellipse,LWPOLYLINE"))))(setq i 0)(setq ll 0)(repeat (sslength en)(setq ss (…

beetl 页面标签_05.Beetl标签函数以及定界符、占位符介绍---《Beetl视频课程》

标签函数 layout所谓标签函数,即允许处理模板文件里的一块内容,功能等于同jsp tag。如Beetl内置的layout标签index.htmllayout("/inc/layout.html",{title:主题}){%>Hello,this is main partlayout.htmltitle is ${title}body content ${la…

hql实例 jpa_SpringBoot学习笔记九:Spring Data Jpa的使用

Spring Data Jpa 简介JPAJPA(Java Persistence API)意即Java持久化API,是Sun官方在JDK5.0后提出的Java持久化规范(JSR 338,这些接口所在包为javax.persistence,详细内容可参考https://github.com/javaee/jpa-spec)JPA的出现主要是为了简化持久…

Objects.requireNonNull 方法说明

在写代码的时候,Idea经常会提醒我们可以使用这个方法来进行参数非空检查, 这个方法的源码也非常简单, 如下所示: /*** Checks that the specified object reference is not {code null}. This* method is designed primarily for doing parameter validation in methods* and …

Java service层获取HttpServletRequest工具类的方法

大家都知道 能在Controller/action层获取HttpServletRequest ,但是这里给大家备份的是从代码内部service层获取HttpServletRequest工具类。 具体如下: package com.base.common.sessionutils; import javax.servlet.http.HttpServletRequest; import j…

正则表达式发明者_浅谈正则表达式背后的基本原理

一、写在前面搞编程的都知道正则表达式是什么东西,这里就不多啰嗦了,需要强调的是,这篇文章并不是教你怎么去使用用正则表达式,正则表达式的语法并不是本文的重点,这篇文章的目的就是剥开正则表达式的语法糖&#xff0…

Java8 - 使用 Comparator.comparing 进行排序

使用外部比较器Comparator进行排序 当我们需要对集合的元素进行排序的时候,可以使用java.util.Comparator 创建一个比较器来进行排序。Comparator接口同样也是一个函数式接口,我们可以把使用lambda表达式。如下示例, package com.common;im…

cairo填充_Cairo 图形指南 (5) —— 形状与填充

这一部分,讲述一些基本的以及较为高级的形状绘制及其纯色 (solid color)、图案 (pattern) 与渐变 (gradient) 填充方法。基本形状Cairo 提供了几个用于绘制基本形状的函数。#include#include#includestatic gbooleanon_expose_event (GtkWidget * widget,GdkEventEx…

java集合进行排序的两种方式

java集合的工具类Collections中提供了两种排序的方法,分别是: Collections.sort(List list)Collections.sort(List list,Comparator c) 第一种称为自然排序,参与排序的对象需实现comparable接口,重写其compareTo()方法,方法体中实现对象的比较大小规则,示例如下: 实体类:(基本…

ubuntu编写python脚本_python在ubuntu中的几种方法(小结)

通过ubuntu官方的apt工具包安装通过PPA(Personal Package Archive) 的apt工具包安装通过编译python源代码安装通过ubuntu官方的apt工具包安装安装完成后, 可以用下面的命令进行确认从PPA(Personal Package Archives) 安装apt工具包类似使用apt工具包安装python的工…

Java中String类中compareTo( )方法

compareTo方法是比较简单的,我们可以直接看其源码: 源码如下: public int compareTo(String anotherString) {int len1 value.length;int len2 anotherString.value.length;int lim Math.min(len1, len2);char v1[] value;char v2[] anotherString…

python elif可以单独使用_Python的elif语句怎么用

else和elif语句也可以叫做子句,因为它们不能独立使用,两者都是出现在if、for、while语句内部的。else子句可以增加一种选择;而elif子句则是需要检查更多条件时会被使用,与if和else一同使用,elif是else if 的简写。if和…

SpringMVC接收哪些类型参数参数

支持的数据类型: 基本类型参数: 包括基本类型和 String 类型 POJO 类型参数: 包括实体类,以及关联的实体类 数组和集合类型参数: 包括 List 结构和 Map 结构的集合(包括数组) SpringMVC …

禁用当前的账户win7_系统小技巧:服务客人 开启Windows 10来宾账户

出于安全考虑,Windows 10默认以管理员账户登录,没有开启来宾账户。但对于那些只需在电脑上浏览网页或收看电子邮件的用户,给他们开启来宾账户非常必要。来宾权限或账户的开启,可以通过下面的两种方法。1. 通过系统设置 开启来宾权…