需要解决的问题
首先我们要知道CAS机制是要解决什么问题的。
当同时有多个线程来访问某个共享变量,并对该变量各自的操作,比如++操作,然后写回给这个变量。在不加限制的情况下,很可能发生的一种情况是:线程A和线程B同时读走了此时变量 p 的值(假设为100),各自++操作,然后拿着各自的 p (101)来写回。这个时候线程A先写回,内存中的 p 变成了101,然后线程B再写回,不管内存中的 p 的值是多少,直接写回为101。这就导致了数据丢失的问题。本来应该是102 的结果,现在丢失了一次—++操作。
CAS机制就是来解决这种问题的。
CAS机制的过程
CAS就是Compare and Swap,也就是比较并替换的意思。
CAS机制的过程是:
同样的,线程A和线程B读走了内存中的共享变量 p (100);然后A和B会记录读取变量时该变量的值,接着进行各自的++操作。最后线程A和线程B都带着 p (101)回来写回,假设A先写回,A需要先比对内存中 p 的值和自己读取时记录的值是否相等,只有相等的情况下才会写入内存。这时内存中的变量 p 的值为101,然后B再写回,也会进行比对,发现 p 的值为101,和自己记录的100不相等,那么这次写入就是失败的,这次数据也就不会再去写入。然后线程B需要重新执行一遍读取,++操作,对比的操作,直到写入时内存中的值和读取时内存中的值相同,才会完成写入。
ABA问题
ABA问题是潜藏在CAS机制中的。
同样假设线程A和线程B访问共享变量 p (100),A执行了一次++操作,然后写回内存,这时内存中 p 的值为101。B由于某些原因还没有写回,线程C读取 p ,并执行了一次 - - 操作,然后写入,此时内存中的变量 p 的值为100,与A、B读取时时相同。这时B再写入,发现内存中 p 的值为100,和自己记录的值是相同的,就会直接写入。但这个流程是不对的,变量 p 的值是发生过改变的。
为了解决这个问题我们可以给每个数据加一个版本号。
比如上面说到的变量 p :100 → 101 → 100 → 101就可以变成:
p :100(01)→ 101(01) → 100(02)这时候线程B再来写回就会发现版本号不对,写入失败,重新读取。