CAS
CAS Compare and Swap一种高效实现线程安全性的方法 支持原子更新操作,适用于计数器,序列发生器(给变量自增)等场景。 属于乐观锁机制,号称lock-free。 CAS操作失败时由开发者决定是继续尝试,还是执行别的操作。 CAS思想 包含三个操作数——内存位置(V)、预期值(A)和新值(B) 执行时将内存位置的值与预期值比较,相等则改为新值,不同则不做操作 CAS多数情况下对开发者来说是透明的 J.U.C的atomic包提供了常用的原子性数据类型以及引用、数组等相关原子类型和更新操作工具,是很多线程安全程序等首选。 Unsafe类虽然提供CAS服务,但因能够操纵任意内存地址读写而有隐患 Java 9 以后,可以使用Variable Handle API来替代Unsafe CAS缺点 若循环时间长...
通过redis实现分布式锁
实现分布式锁分布式锁需要解决的问题 互斥性 任一时刻,只能有一个客户端获取锁 安全性 锁只能由持有的客户端删除 死锁 避免某些客户端因宕机等原因未能释放锁,而其他客户端再也无法获取该锁 容错 当部分节点宕机后客户端应仍然能够获取锁和释放锁 如何通过Redis实现分布式锁方案一(不推荐)SETNX key value :如果key不存在,创建并赋值 时间复杂度O(1) 返回值:key不存在,设置成功,返回1,key存在则失败返回0 因为setnx是原子的又有以上特性,初期被用来实现分布式锁 执行某段代码时先尝试使用SETNX对某个key设值,如果设置成功,则证明没有别的线程在执行该段代码。 如何解决SETNX长期有效的问题?EXPIRE key secons 设置key的生存时间,当key过期时会被自动删除 此方法的问题如果一个线程设置了key还没来得及设置过期时间就宕机了,就会发生死锁 主要原因就是原子性不能得到满足 方案二将SETNX和EXPIRE放在一块执行 SET key value [EX seconds] [PX milliseconds]...
使用Redis做异步队列
使用Redis做异步队列使用List作为队列,RPUSH生产消息,LPOP消费消息缺点一: 没有等待队列里有值就直接消费 第一种弥补方案: 可以通过在应用层引入Sleep机制去调用LPOP重试 第二种弥补方案:使用命令: BLPOP key [key...] timeout 阻塞直到队列有消息或者超时 缺点二: 只能供一个消费者消费 弥补:pup/sub:主题订阅者模式 发送者(pup)发送消息,订阅者(sub)接收消息。 订阅者可以订阅任意数量的频道 订阅频道: subscribe channel [channel...]发布消息:PUBLIC channel Message此方法的缺点: 消息的发布是无状态的,不能保证可达 要解决此问题只能使用专业的消息队列如kafaka等