CAS

并发数据结构:迷人的原子

为君一笑 提交于 2020-03-05 01:47:21
随着多核CPU成为主流,并行程序设计亦成为研究领域的热门。 要想利用多核/多路CPU带来的强大功能,通常使用多线程来开发应用程序。但是要想拥有良好的硬件利用率,仅仅简单的在多个线程间分割工作是不够的。还必须确保线程大部分时间在工作,而不是在等待工作或等待锁定共享数据结构。 在不止一个线程访问共享数据时,所有线程都必须使用同步。如果线程间不进行协调,则没有任务可以真正并行,更糟糕的是这会给程序带来毁灭性的错误。 现在让我们来看一下在.NET和D语言中的标准同步手段-锁定。.NET下我们使用lock关键字,而D语言则使用 synchronized关键字。它们在Windows下均使用临界区(Critical Section)来实现,而在Linux下则使用互斥锁(Mutex)来实现。不论其如何实现,它们均强制实行互斥,来确保持有锁的线程对共享数据的独占访问权,以及当其他线程持有锁时,可以看到其对共享数据的修改。 简而言之,在基于锁的多线程编程中,任何针对共享数据,且有可能导致竞争条件的操作,我们都得将其改为原子操作(即连续的,不允许被打断的步骤;上面的lock/ synchronized 关键字就是我们实现原子操作的手段)。只要我们的线程持有锁,就不必担心其他线程会进来捣乱。 这听起来似乎很不错,我们只要加锁/解锁就可以为所欲为了。然而正是这种为所欲为的事实带来了问题

CAS单点登录原理

最后都变了- 提交于 2020-03-04 19:11:42
转自 https://www.cnblogs.com/lihuidu/p/6495247.html 1、基于Cookie的单点登录的回顾 基于Cookie的单点登录核心原理: 将用户名密码加密之后存于Cookie中,之后访问网站时在过滤器(filter)中校验用户权限,如果没有权限则从Cookie中取出用户名密码进行登录,让用户从某种意义上觉得只登录了一次。 该方式缺点就是多次传送用户名密码,增加被盗风险,以及不能跨域。同时www.qiandu.com与mail.qiandu.com同时拥有登录逻辑的代码,如果涉及到修改操作,则需要修改两处。 2、统一认证中心方案原理 在生活中我们也有类似的相关生活经验,例如你去食堂吃饭,食堂打饭的阿姨(www.qiandu.com)告诉你,不收现金。并且告诉你,你去门口找换票的(passport.com)换小票。于是你换完票之后,再去找食堂阿姨,食堂阿姨拿着你的票,问门口换票的,这个票是真的吗?换票的说,是真的,于是给你打饭了。 基于上述生活中的场景,我们将基于Cookie的单点登录改良以后的方案如下: 经过分析,Cookie单点登录认证太过于分散,每个网站都持有一份登陆认证代码。于是我们将认证统一化,形成一个独立的服务。当我们需要登录操作时,则重定向到统一认证中心http://passport.com。于是乎整个流程就如上图所示: 第一步

CAS单点登录原理解析

点点圈 提交于 2020-03-04 19:09:54
转自: https://www.cnblogs.com/lihuidu/p/6495247.html 1、基于Cookie的单点登录的回顾 基于Cookie的单点登录核心原理: 将用户名密码加密之后存于Cookie中,之后访问网站时在过滤器(filter)中校验用户权限,如果没有权限则从Cookie中取出用户名密码进行登录,让用户从某种意义上觉得只登录了一次。 该方式缺点就是多次传送用户名密码,增加被盗风险,以及不能跨域。同时www.qiandu.com与mail.qiandu.com同时拥有登录逻辑的代码,如果涉及到修改操作,则需要修改两处。 2、统一认证中心方案原理 在生活中我们也有类似的相关生活经验,例如你去食堂吃饭,食堂打饭的阿姨(www.qiandu.com)告诉你,不收现金。并且告诉你,你去门口找换票的(passport.com)换小票。于是你换完票之后,再去找食堂阿姨,食堂阿姨拿着你的票,问门口换票的,这个票是真的吗?换票的说,是真的,于是给你打饭了。 基于上述生活中的场景,我们将基于Cookie的单点登录改良以后的方案如下: 经过分析,Cookie单点登录认证太过于分散,每个网站都持有一份登陆认证代码。于是我们将认证统一化,形成一个独立的服务。当我们需要登录操作时,则重定向到统一认证中心http://passport.com。于是乎整个流程就如上图所示: 第一步

cas单点登录原理

你。 提交于 2020-03-04 19:02:59
1、基于Cookie的单点登录    原理:   将用户名密码加密智斗存于Cookie中,之后访问网站时在过滤器校验用户权限,如果没有权限则从Cookie中取出用户名密码进行登录,让用户觉得 只登录了一次。 2、统一认证中心方案原理   在生活中我们也有类似的相关生活经验,例如你去食堂吃饭,食堂打饭的阿姨(www.qiandu.com)告诉你,不收现金。并且告诉你,你去门口找换票的(passport.com)换小票。于是你换完票之后,再去找食堂阿姨,食堂阿姨拿着你的票,问门口换票的,这个票是真的吗?换票的说,是真的,于是给你打饭了。   基于上述生活中的场景,基于Cookie的单点登录改良以后的方案如下:        经过分析,Cookie单点登录认证太过于分散,每个网站都持有一份登录认证代码。于是将认证统一化,形成一个独立的法务。 当需要登录操作时,则重定向到同意认证中心http://passport.com。整个流程如上图所示:   1:用户访问www.qiandu.com。过滤器判断用户是否登录,没有登录,则重定向(302)到网站http://passport.com。   2、重定向到passport.com。输入用户名密码。passport.com将用户登录的信息记录到服务器的session中。   3、passport.com给浏览器发送一个特殊凭证

关于Synchronized的各种锁

本秂侑毒 提交于 2020-03-04 16:50:25
执行流程如下: 1.当一个线程(假设叫A线程)想要获得锁时,首先检查对象头中的锁标志,如果是偏向锁,则跳转到2,如果是无锁状态,则跳转到 2.检查对象头中的偏向线程id是否指向A线程,是,则直接执行同步代码块,不是则3。 3.使用cas操作将替换对象头中的偏向线程id,成功,则直接执行同步代码块。失败则说明其他的线程(假设叫B线程)已经拥有偏向锁了,那么进行偏向锁的撤销(因为这里有竞争了),此时执行4。 4.B线程运行到全局安全点后,暂停该线程,检查它的状态,如果处于不活动或者已经退出同步代码块则原持有偏向锁的线程释放锁,然后A再次执行3。如果仍处于活动状态,则需要升级为轻量级锁,此时执行5。 5.在B线程的栈中分配锁记录,拷贝对象头中的MarkWord到锁记录中,然后将MarkWord改为指向B线程,同时将对象头中的锁标志信息改为轻量级锁的00,然后唤醒B线程,也就是从安全点处继续执行。 6.由于锁升级为轻量级锁, A线程也进行相同的操作,即,在A线程的栈中分配锁记录,拷贝对象头中的Mark Word到锁记录中,然后使用cas操作替换MarkWord,因为此时B线程拥有锁,因此, A线程自旋。如果自旋一定次数内成功获得锁,那么A线程获得轻量级锁,执行同步代码块。若自旋后仍未获得锁,A升级为重量级锁,将对象头中的锁标志信息改为重量级的10,同时阻塞,此时请看7。 7

java源码学习---ConcurrentHashMap

孤街浪徒 提交于 2020-03-04 01:35:07
ConcurrentHashMap与 HashMap 一样,都是键值对数据存储结构,不过 HashMap 是非线程安全,而ConcurrentHashMap是线程安全的,说起线程安全又不得不与HashTable对比一下,HashTable相比ConcurrentHashMap效率低,接下来看看ConcurrentHashMap到底是如何保证线程安全且比HashTable优秀(JDK1.8) 还是从put()开始 public V put( K key, V value) { return putVal(key, value, false ); } put()会再调一个putValue(),因为要传入 onlyIfAbsent 参数同意更新元素,与HashMap不一样的是 key的散列算法不是在put()完成,而是在putValue()完成 /** * key: 储存到 HashMap 的 key * value: 储存到 HashMap 的 key 对应的 value * onlyIfAbsent: 如果包含了该 key ,则不更新对应的值,众所周知, put() 除了新增之外,还有更新的功能,是因为 put() 调用 putVal() 时候传的都是 false */ final V putVal(K key, V value, boolean onlyIfAbsent) { /

java集合框架-ConcurrentHashMap线程安全的底层实现

心已入冬 提交于 2020-03-03 18:23:37
JDK1.7 首先将数据分为一段一段存储,然后给每段数据配一把锁,当一个线程占用访问其中一个段数据时,其他数据段能被其他数据访问。 ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。其中Segment实现了ReentrantLock,所以Segment是一种可重入锁。HashEntry用于存储键值对数据。 JDK1.8 数据结构和HashMap类似。采用数组+链表/红黑树。使用CAS和synchronized保证并发。synchronized只锁住当前链表或红黑树的首节点,这样是要hash不冲突,就不会产生并发冲突。 来源: oschina 链接: https://my.oschina.net/u/3991724/blog/3186748

cas单点登录集群如何优雅的退出

时光毁灭记忆、已成空白 提交于 2020-03-02 12:32:11
实现cas ticket基于redis的集群 目的 克服cas单点故障,将cas认证请求分发到多台cas服务器上,降低负载。 实现思路: 采用统一的ticket存取策略,所有ticket的操作都从中央缓存redis中存取。 采用session共享,session的存取都从中央缓存redis中存取。 前提: 这里只讲解如何实现cas ticket的共享,关于session的共享请移步: https://github.com/izerui/tomcat-redis-session-manager 实现步骤: 基于cas源码 新增模块 cas-server-integration-redis pom.xml 文件如下: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cas-server</artifactId>

CAS服务端redis集群搭建

空扰寡人 提交于 2020-03-02 11:26:40
注 :cas4.0.x+Tomcat7+Jdk7+redis3.0 CAS中的票据默认是存储在TicketRegistry中的,若是想要实现CAS服务端的集群,首先要做的是将票据共享到缓存中。 1.实现 AbstractDistributedTicketRegistry 抽象类 import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.Collection; import javax.validation.constraints.Min; import org.jasig.cas.ticket.ServiceTicket; import org.jasig.cas.ticket.Ticket; import org.jasig.cas.ticket.TicketGrantingTicket; import org.jasig.cas.ticket.registry.AbstractDistributedTicketRegistry; import org.springframework.beans.factory

一直使用AtomicInteger?试一试FieldUpdater

我的梦境 提交于 2020-03-01 23:46:44
1. 背景 在进入正题之前,这里先提出一个问题,如何在多线程中去对一个数字进行+1操作?这个问题非常简单,哪怕是Java的初学者都能回答上来,使用AtomicXXX,比如有一个int类型的自加,那么你可以使用AtomicInteger 代替int类型进行自加。 AtomicInteger atomicInteger = new AtomicInteger(); atomicInteger.addAndGet(1); 如上面的代码所示,使用addAndGet即可保证多线程中相加,具体原理在底层使用的是CAS,这里就不展开细讲。基本上AtomicXXX能满足我们的所有需求,直到前几天一个群友(ID:皮摩)问了我一个问题,他发现在很多开源框架中,例如Netty中的AbstractReferenceCountedByteBuf 类中定义了一个refCntUpdater: private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> refCntUpdater; static { AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> updater = PlatformDependent