互斥性与幂等性 我觉得这两个特性是在系统分析和设计时必须考虑的问题。开始之前,先简单解释下两者的概念。 什么是互斥性 要解释互斥性就不得不先提一下 临界资源,引用百科的介绍。 一次仅允许一个进程使用的资源称为临界资源。 很显然,当多方共享临界资源时,那么这些使用方是互斥的。 举一些场景: 多个人同时修改同一个文档 多个线程一起修改一个并发不安全的Map 假设程序不保证互斥性: 让大家一起修改,那么: 场景一:最后只会保留最后一个处理的修改,其他的修改都会丢失 场景二:在多线程同时写入内存时会因为竞争关系出现数据错乱,有兴趣的同学可以看下这篇文章 为什么你的并发程序不安全。 这些显然是我们不愿看见的情况,所以保证互斥性对于临界资源的使用是非常重要的,保证互斥性的过程其实也是保证并发安全性的过程。 这里再多说下一些进程内的情况,比如多个线程对一个变量的读写,一写多读,需不要保证互斥性? 答案是要。 这里涉及到两个原因: 哪怕你的语句是一条汇编的原子操作(比如MOV xxxx, xxxx) 都不一定是原子操作。 多线程操作时,可能位于不同CPU上执行,修改对其他在其他CPU上执行的线程来说并不是马上可见的 基于以上原因,那怕是对一个bit的操作,也需要考虑互斥性。 什么是幂等性 幂等原本是数学的概念,表示某个运算执行任意多次与一次的结果相同。 后来引用到系统设计中,指具备该性质的接口在相同的参数下,调用一次与多次结果相同。 显然,有一些类别的接口天生就是幂等的,比如 查询 和 删除。 幂等性的重要性在于消除重复提交来带的副作用。 考虑下面的场景 某个人在同一页面多次提交对文档的修改(假设页面没有二次防押) 某个秒杀环节中,通过消息中间件来分摊处理的压力,但是消息中间件由于各种不可控因素投递了两次相同的消息 假设接口不保证幂等性,那么: 场景一:加大了存储系统的负担,如果同一时间很多这样操作的用户,可能会引发服务雪崩。 场景二: 如果消费的逻辑没有保证幂等,那么就会生成两条相同的订单 互斥性的解决方案 引用下在美团技术沙龙的 分布式系统互斥性与幂等性问题的分析与解决 出现的一句话 基本上所有的并发模式在解决线程冲突问题的时候,都是采用序列化访问共享资源的方案。 我觉得这句话很棒,在 «七周七并发模式» 书中出现的并发模式比如 CSP, Actor其实本质上也都是把对共享资源的请求串行化了,比如 CSP 是将请求都放入 Channel 中,而 Actor 则放入了 MailBox。