CAS

CAS中的ABA问题

孤街浪徒 提交于 2020-03-01 17:51:45
经典的ABA问题: ABA问题存在CAS无锁方案中,我们写一个CAS的伪代码栗子: class SimulatedCAS{ volatile int count; int newValue; //实count+=1 addOne(){ do { newValue=count+1; //① }while(count != cas(count,newValue) )//② } //模拟实现CAS,仅⽤来帮助理解 synchronized int cas( int expect, int newValue){ // 读⽬前count的值 int curValue=count; // ⽐较⽬前count值是否==期望值 if(curValue==expect){ // 如果是,则更新count的值 count=newValue; } // 返回写⼊前的值 return curValue; } } 假设 count原本是 A,线程 T1 在执行完代码①处之后,执行代码②处之前,有可能 count 被线程 T2 更新成了 B,之后又被 T3 更新回了 A,这样线程 T1 虽然看到的一直是 A, 但是这个值其实已经被其他线程更新过了,这就是 ABA 问题 。 如何解决: 最简单的方案就是给值加一个修改版本号,每次值变化,都会修改它版本号,CAS操作时都对比此版本号。

JAVA并发编程:干掉 Synchronized

青春壹個敷衍的年華 提交于 2020-03-01 17:13:18
Synchronized 是通过实例对象的monitor来实现的。 Synchronized 能锁住的两种方式: 锁对象 锁对象,只锁定当前对象本身,其他的实例对象,不能同时锁定 在方法上 //锁对象方法 public void synchronized sync() 在对象上 //锁this对象 public void sync(){ synchronized(this){ } } 上面两者是等价的,都是锁在当前对象上。只锁自己的对象 锁类 锁类上,是对当前类所有的实例对象加锁 //锁静态方法 public static void synchronized sync() //锁类字节 public void sync(){ synchronized(Students.class){ } } 对类字节进行锁定,则锁定的是JVM内,此类的所有对象。 这个是怎么处理的呢? 以什么为标识来锁的呢? Synchronized 是通过monitor来实现锁定的,每一个对象都有自己的monitor, monitor中维护了两个列表,_EntrySet和_WaitSet, 这两个是做什么的呢?结合下图来说明。 _EntrySet : 当 A 线程拿到 monitor锁,对 monitor 进行计数加 1,B 线程再去获取锁是获取不到的。此时 B 线程进入 _EntrySet 列表中等待。 当然

2020-02-29

房东的猫 提交于 2020-03-01 12:08:38
最近在部署环境中,node.js调用cas实现单点登录,cas对应nginx服务器域名地址为https……。发送请求后,出现错误:unable to verify the first certificate,查看cas日志,认证成功。最好返回状态为401,这是什么原因,有遇到过的么?是否和域名https的证书有关系? 来源: CSDN 作者: pl2e37mv 链接: https://blog.csdn.net/pl2e37mv/article/details/104571670

偏向锁、轻量级锁、重量级锁区别与联系

百般思念 提交于 2020-03-01 05:53:55
今天总结了锁升级(偏向锁、轻量级锁、重量级锁)和锁优化下面开始总结。 其实这些内容都是JVM对锁进行的一些优化,为什么分开讲,原因是锁升级比较重要,也比较难。 一、锁升级 在1.6之前java中不存在只存在重量级锁,这种锁直接对接底层操作系统中的互斥量(mutex),这种同步成本非常高,包括操作系统调用引起的内核态与用户态之间的切换。线程阻塞造成的线程切换等。因此在jdk 1.6中将锁分为四种状态:由低到高分别为:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态。 1. 偏向锁。什么是偏向锁呢?为什么要引入偏向锁呢? 偏向锁是如果一个线程获取到了偏向锁,在没有其他线程竞争的情况下,如果下次再执行该同步块时则只需要简单判断当前偏向锁所偏向的对象是否是当前线程,如果是则不需要再进行任何获取锁与释放锁的过程,直接执行同步块。至于为什么引入偏向锁,是因为经过JVM的开发人员大量的研究发现大多数时候都是不存在锁竞争的,通常都是一个线程在使用锁的时候没有其他线程来竞争,然而每次都要进行加锁和解锁就会额外增加一些没有必要的资源浪费。为了降低这些浪费,JVM引入了偏向锁。 a) 偏向锁的获取以及升级过程如下: 当一个线程在执行同步块时,它会先获取该对象头的MarkWord,通过MarkWord来判断当前虚拟机是否支持偏向锁(因为偏向锁是可以手动关闭的),如果不支持则直接进入轻量级锁获取过程

java 面试知识点笔记(十)多线程与并发-原理 上篇

∥☆過路亽.° 提交于 2020-03-01 01:28:46
问:线程安全问题的主要诱因? 存在共享数据(也称临界资源) 存在多条线程共同操作这些共享数据 解决方法:同一时刻有且只有一个线程在操作共享数据,其他线程必须等到该线程处理完数据后再对共享数据进行操作 互斥锁的特征: 互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程协调机制,这样在同一时间只有一个线程对需要同步的代码块(复合操作)进行访问。互斥性也称为操作的原子性。 可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的(即在获得锁时应该获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作,从而引起不一致。 ps:synchronized 锁的不是代码,锁的是对象 获取锁的分类:获取对象锁、获取类锁 获取对象锁的两种用法: 同步代码块(synchronized(this),synchronized(类实例对象)),锁是小括号中的实例对象 同步非静态方法(synchronized method) 锁是当前对象的实例对象 获取类锁的两种用法: 同步代码块(synchronized(类.class)),锁是小括号中的类对象(Class对象) 同步非静态方法(synchronized static method) 锁是当前对象的类对象(Class对象) 类锁和对象锁在锁同一个对象的时候表现行为是一样的

CAS你知道吗?

百般思念 提交于 2020-02-28 23:49:24
CAS 是什么??? 1、比较并交换(CompareAndSet)通过简单的Demo来看 package com . brian . interview . study . thread ; /** * Copyright (c) 2020 ZJU All Rights Reserved * <p> * Project: JavaSomeDemo * Package: com.brian.interview.study.thread * Version: 1.0 * <p> * Created by Brian on 2020/2/11 0:47 */ import java . util . concurrent . atomic . AtomicInteger ; /** * 1、 CAS是什么? ===> CompareAndSet * 比较并交换 */ public class CASDemo { public static void main ( String [ ] args ) { AtomicInteger atomicInteger = new AtomicInteger ( 5 ) ; // main do thing ...... System . out . println ( atomicInteger . compareAndSet ( 5 , 2020

Lock和sycnoized性能对比

删除回忆录丶 提交于 2020-02-28 23:45:59
现在测试不同线程下的表现(时间单位ms): 1 10 50 100 500 1000 5000 synchronized 542 4894 4667 4700 5151 5156 5178 lock 838 1211 821 847 851 1211 1241 可以看到,在多线程环境并存在大量竞争的情况下,synchronized的用时迅速上升,而lock却依然保存不变或增加很少。 Lock是用CAS来实现的 JDK 1.6以上synchronized也改用CAS来实现了,所以两者性能差不多 Lock提供的功能丰富点,synchronized的使用简单点 来源: oschina 链接: https://my.oschina.net/u/1455908/blog/383002

(java并发)CAS操作原理以及Atomic的原理

心已入冬 提交于 2020-02-28 21:05:17
CAS操作可以分为以下三个步骤: 步骤 1. 读旧值(即从系统内存中读取所要使用的变量的值,例如:读取变量i的值) 步骤2. 求新值(即对从内存中读取的值进行操作,但是操作后不修改内存中变量的值,例如:i=i+1,这一步只进行 i+1,没有赋值,不对内存中的i进行修改) 步骤3. 两个不可分割的原子操作 第一步: 比较内存中变量现在的值与 最开始读的旧值是否相同(即从内存中重新读取i的值,与一开始读取的 i进行比较) 第二步: 如果这两个值相同的话,则将求得的新值写入内存中(即:i=i+1,更改内存中的i的值) 如果这两个值不相同的话,则重复步骤1开始 注:这两个操作是不可分割的原子操作,必须两个同时完成 CAS操作 CAS是单词compare and set的缩写,意思是指在set之前先比较该值有没有变化,只有在没变的情况下才对其赋值。 我们常常做这样的操作 if(a==b) { a++; } 试想一下如果在做a++之前a的值被改变了怎么办?a++还执行吗?出现该问题的原因是在多线程环境下,a的值处于一种不定的状态。采用锁可以解决此类问题,但CAS也可以解决,而且可以不加锁。 int expect = a; if(a.compareAndSet(expect,a+1)) { doSomeThing1(); } else { doSomeThing2(); }

CAS原理分析及ABA问题详解

空扰寡人 提交于 2020-02-28 20:36:54
什么是CAS CAS 即 Compare And Swap 的缩写,翻译成中文就是 比较并交换 ,其作用是让CPU比较内存中某个值是否和预期的值相同,如果相同则将这个值更新为新值,不相同则不做更新,也就是CAS是 原子性 的操作(读和写两者同时具有原子性),其实现方式是通过借助 C/C++ 调用CPU指令完成的,所以效率很高。 CAS 的原理很简单,这里使用一段 Java 代码来描述 public boolean compareAndSwap(int value, int expect, int update) { // 如果内存中的值value和期望值expect一样 则将值更新为新值update if (value == expect) { value = update; return true; } else { return false; } } 大致过程是将内存中的值、我们的期望值、新值交给CPU进行运算,如果内存中的值和我们的期望值相同则将值更新为新值,否则不做任何操作。这个过程是在CPU中完成的,这里不好描述CPU的工作过程,就拿Java代码来描述了。 Unsafe源码分析 Java是在 Unsafe(sun.misc.Unsafe) 类实现 CAS 的操作,而我们知道Java是无法直接访问操作系统底层的API的

基础图解之分布式服务部署请求流程

你。 提交于 2020-02-28 18:52:00
今天,深层次和群里同学讨论关于分布式系统问题 汇总如下: 单体应用,分布式部署:保存会话信息(spring-session) 客户端cookies + 服务端 redis = 用户信息 单机应用中,HttpSession是通过Servlet容器创建和管理的,servlet容器一旦停止服务,那么session也随之消失;但如果session被保存到redis中,只要redis服务没停且session在有效期间内,那么servlet容器停止服务了,session还是存在的,这有什么好处了,好处就是servlet容器出现闪停闪修复的情况,用户就不用重新登录了。 使用redis存储用户会话信息,客户端web请求每次携带cookies,在拦截器中,获取通过cookies获取redis中用户信息 集群部署时(3台服务器部署3个tomcat, 其中tomcat部署同一个项目) ,其session是无法共享的, 可以使用 spring-session 共享session ; 分布式应用:保存会话信息(sso单点登录) sso登录 分布式系统部署时, 多服务器, session是无法共享的,这是公认的, 同时顶级域名下, 不同服务,前端请求是无法跨域获取cookie的,要想实现效果, 参考使用 sso登录 模式; 逻辑: 抽离登录业务逻辑为公共服务,统一验证是否登录未登录,反馈cookies等参数;