j.u.c中atomic实现原理

一. atomic包与JMM

并发包下的atomic下的有很多支持原子性的类:

AtomicBoolean,AtomicInteger,AtomicLong,AtomicReference…等等,

如果你在代码中使用一个他们中的一个做为变量的话,可以让这个变量变成所有线程都共享的,都可见的.

这里不得不要数一下,java内存模型(JMM),通常来说我们启动程序时使用的启动参数一般是:-Xms512m -Xmx512m -Xss128k,前面两个我们都比较熟悉,他们是堆栈最大最小值,一般会设置相同,这是为了防止GC过后对堆栈地址的重新分配,而造成的不必要的性能浪费,而最后这个参数是虚拟机的线程堆栈的大小,在JDK1.5之前默认大小是128k,jDK1.5以后是1m.相同的内存下更小的堆栈大小,可以创建更多的线程,但是一般系统会对一个进程内所能创建的线程数是有限制的.

这里就引出的JMM:


举个栗子:这里如果我们使用的main()方法启动程序,这个时候jvm就启动一个叫main的线程运行程序,jvm会给main线程一个 -Xss设置的私有内存大小的内存给main;

这个时候如果main要获取一个变量的值,首先会去栈中获取变量的堆地址(哈希值),再去堆中读取,读到后放到自己的线程内存中,读完后在放回去,这个线程内存是私有的,而要改变一个值的时候也是通过写操作去改变.

如图所示这个时候会涉及到我们常说的并发问题,经典的就是银行取钱,怎么保证同事操作而不将钱取成负数,JMM有共享内存区域,他可以保证对象的全线程可见性,所有的线程都可见,操作共享内存的值,但是又有新的问题,假如共享内存中有一个int num=100,因为所有线程都可见,线程a,读到int num=100,当做完逻辑判断的时候需要将num 做一个-50的操作,但是可能num已经被线程b变成num=30,这个时候再进行操作就会变成-20,变成负数不符合业务逻辑.

这里就要引入CAS的概念,既:CompareAndSwap(对比和交换),也就是在进行update操作的时候先用预期值对比现在内存中的值,相等的情况下,再去做更新,这就能有效的避免上面说到的情况.

而atomic就是基于CMS而开发的包装类,说通俗一点就是支持CAS的Integer,Boolean,Long,Reference…

二. atomic源码

1.AtomicBoolean中首先定义了一个私有的int变量 value,注意这是使用volatile修饰,(volatile修饰的变量会放入到共享内存中让所有的工作线程可见).

2.AtomicBoolean的构造器是将initialValue变成 int值更改value值


3.提供compareAndSet()方法,预期值 expect,要更新成的新值 update,而下面这个Unsafe对象,是sun.misc.Unsafe.是jdk中sun包的一个工具类,里面提供了很多CAS操作的方法.而J.U.C atomic包下的所欲CAS操作都是使用了这个工具类的方法.

(菜鸟拙见,不对的地方欢迎指正
2018年8月21日11:16:36)

你可能感兴趣的:(java并发包源码阅读)