Java并发学习之原子性

原子性简单定义为提供了互斥访问,同一时刻只能有一个线程来进行操作。

可见性则是一个线程对主内存的修改可以及时被其他线程发现。

有序性是一个线程观察其他线程中的指令执行顺序,由于指令重排序的存在,观察结果一般杂乱无序。

原子性在java中提供了Atomic包。



/**

* 线程池的基本大小

*/

static int corePoolSize =1000;

/**

* 线程池最大数量

*/

static int maximumPoolSizeSize =2000;

/**

* 线程活动保持时间

*/

static long keepAliveTime =5;

/**

* 任务队列

*/

static ArrayBlockingQueueworkQueue =new ArrayBlockingQueue(10);

/**

* 计数

*/

private static AtomicInteger count =new AtomicInteger(0);

//定义请求总数

public static int clientTotal =8000;

//定义并发同时执行数

public static int threadTotal =200;

public static void main(String[] args)throws InterruptedException {

//推荐手动创建线程池

    ThreadPoolExecutorexecutor =new ThreadPoolExecutor(

corePoolSize,

maximumPoolSizeSize,

keepAliveTime,

TimeUnit.SECONDS,

workQueue,

new ThreadPoolExecutor.AbortPolicy());

//控制线程并发的数量

    final Semaphoresemaphore =new Semaphore(threadTotal);

//计数器count

    final CountDownLatchcountDownLatch =new CountDownLatch(clientTotal);

for (int i =0; i

executor.execute(() -> {

try {

semaphore.acquire();

addInt();

semaphore.release();

}catch (Exception e) {

log.error("错误信息:{}", e);

}

//计数器--

            countDownLatch.countDown();

});

}

countDownLatch.await();

executor.shutdown();

log.info("count :{}",count.get());

}

private static void addInt() {

count.getAndIncrement();

}

我们运行这段代码得到的答案是:8000

体现不出Atiomic的作用 那么我们把Atiomic 去掉换成普通的int 会成为怎么样的结果?得到的结果是没有准确性的

可能是 7999 或者 7998 或者8000 或者更多的答案。

这个是 getAndIncrement 的源码 

/**

* Atomically increments by one the current value.

*

* @return the previous value

*/

public final int getAndIncrement() {

return unsafe.getAndAddInt(this,valueOffset,1);

}

那么底层到底做了什么让他线程安全?

Java并发学习之原子性_第1张图片

可以看到compareAndSwapInt  里面传参 var1 参数 当前对象 比如 count   ,var 2 比如我传的是2。var 4 为 1,

那么var 5 则是我们调用底层方法 得到的当前值 2。 这个var 5 怎么是2 ,请看 Java并发学习之java内存模型JMM

我们用底层得到的值去加上需要改变的值 也就是 2+1 。当然这个地方 是比较了 var2 的值与var5的值是否相等!

通过 循环判断 来覆盖底层的值。 

也可以看见compareAndSwapInt 三个 单词的开头CAS 的由来。

有大佬今天问我CAS原理。。 站在我的角度讲,应该从JMM来讲,当线程去修改一个值,这个值获取的是主内存的值,还是CPU线程缓存区的值? 肯定是线程缓存区(工作内存)的值,获取完毕修改写入主存。至于底层调用的C++去干了什么了解了一下,贴出链接  Java中的CAS实现原理  包括其中介绍了CAS的ABA问题以及解决方案。

本文仅限本人小白学习参考,不足之处请大佬指正。

你可能感兴趣的:(Java并发学习之原子性)