![fbe6580c41abec644942b25baafb0f7b.png](https://img-blog.csdnimg.cn/img_convert/fbe6580c41abec644942b25baafb0f7b.png)
大家好,我是小杨,微信公众号码猿Bug,由于现在实在是太忙了,今天晚上11点开始写这篇拖了很久的文章,后续会给大家继续写出并发的知识和框架的源码,也是为平常学习的过程中积累的知识。
为什么在AtomicInteger中CAS而不用Synchronized呢?
- 首先清楚一点,使用Synchronized的话,是多个线程抢一份资源,相对来说Semaphore就好比是多个线程抢多个资源,信号增Semaphore这个概念后续文章会给大家讲到。回归正题,Synchronized是只允许一个线程运行,虽然一致性保证了,但是降低并发性,而cas底层是unsafe,并且不加锁,保证一致性,允许多个线程同时操作,并发量得到保障,但是循环比较。
CAS有什么缺点呢?
1.循环时间长,开销大,源码如下:
![46d032ac93af817388d14cf5f384b738.png](https://img-blog.csdnimg.cn/img_convert/46d032ac93af817388d14cf5f384b738.png)
2.只能保证一个共享变量的原子操作,这个就很好理解了
3.最主要的就是ABA问题,那么什么是ABA问题呢?接下来重点讲解
CAS算法实现一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并交换,那么在这个时间差内会导致数据的变化,举例加图解说明:
比如一个线程One从内存中取出A,这时候另一个线程Two也从内存中取出A,并且线程Two做了一些操作将值改成了B,此时内存中的值就为B,但是线程Two继续对内存中的B操作,又改回了A,所以此时内存中的值还是A,此时线程One进行cas操作发现内存中的值依然是A,然后线程One操作成功。
![1ea9e2ea1a68d7acee93a7ffd1439f97.png](https://img-blog.csdnimg.cn/img_convert/1ea9e2ea1a68d7acee93a7ffd1439f97.png)
图画的有点不好看,但是大概的意思能看明白,尽管线程One能操作成功,但是不代表这个过程是没有问题的。那么怎么解决呢?
AtomicReference<V>原子引用,有了泛型,这样就不单单是AtomicInteger和AtomicBoolean等等了,也可以是类
如何解决cas造成的ABA问题呢?原子引用+新增一种机制,那就是修改版本号(类似时间戳)AtomicStampedReference(带时间戳的原子引用):时间戳原子引用,类似于数据库中的乐观锁实现一样,加一个版本号控制。就不用代码演示了,道理和AtomicInteger是差不对的。
下面缓解一下,给初级的同学们出一道题,初级的话是很容易犯错的,下一篇文章中会附带答案。
public static void main(String[] args) {
int age=10;
Demo1 demo1 = new Demo1();
demo1.changeValue1(age);
System.out.println("age="+age);
System.out.println("------------");
Person person = new Person("老潘");
demo1.changeValue2(person);
System.out.println("personName"+person.getPersonName());
System.out.println("-----------------");
String str="abc";
demo1.changeValue3(str);
System.out.println("str="+str);
}
public void changeValue1(int value){
value=20;
}
public void changeValue2(Person person){
person.setPersonName("发发");
}
public void changeValue3(String str){
str="xxx";
}
今天就写到这,太累了,要睡了,最近几天会疯狂补上文章,大家可以好好看看,到了源码和重要的难理解的知识点我会一步一步,一点一点的为大家讲解,很详细!