博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一段JAVA代码了解多线程,JUC、CAS原子性操作。
阅读量:6697 次
发布时间:2019-06-25

本文共 3806 字,大约阅读时间需要 12 分钟。

@Test    public void testPaceController_multiThread() throws InterruptedException {        final PaceController paceController = new PaceController(1000, 160d);        final Node node = mock(Node.class);        final AtomicInteger passcount = new AtomicInteger();        final AtomicInteger blockcount = new AtomicInteger();        final AtomicInteger done = new AtomicInteger();       AtomicLong lastTm = new AtomicLong(System.currentTimeMillis() / 1000);        int count = 1000;        final CountDownLatch countDown = new CountDownLatch(count);        for (int i = 0; i < count; i++) {            Thread thread = new Thread(new Runnable() {                @Override                public void run() {                    for(int j =0; j< 10; j++) {                        boolean pass = paceController.canPass(node, 1).isPass();                        if (pass == true) {                            passcount.incrementAndGet();                        } else {                            blockcount.incrementAndGet();                        }                        done.incrementAndGet();                        long now = System.currentTimeMillis() / 1000;                        if (lastTm.get() != now) {                            System.out.println("pass:" + passcount.get() + ", tm:" + lastTm.get());                            System.out.println("block:" + blockcount.get() + ", tm:" + lastTm.get());                            System.out.println("done:" + done.get() + ", tm:" + lastTm.get());                            passcount.set(0);                            blockcount.set(0);                            done.set(0);                        }                        lastTm.set(now);                    }                    countDown.countDown();                }            }, "Thread " + i);            thread.start();        }        countDown.await();        System.out.println("pass:" + passcount.get() + ", tm:" + lastTm.get());        System.out.println("block:" + blockcount.get() + ", tm:" + lastTm.get());        System.out.println("done:" + done.get() + ", tm:" + lastTm.get());    }
1.CountDownLatch 同步并发处理
countDown.countDown 递减为0,等待发射信号。 countDown.await()阻塞当前线程,等待调用。
2.AtomicInteger 和 volatile 的区别,CAS原子性操作。

volatile关键字很重要的两个特性:

1、保证变量在线程间可见,对volatile变量所有的写操作都能立即反应到其他线程中,换句话说,volatile变量在各个线程中是一致的(得益于java内存模型—"先行发生原则");

2、禁止指令的重排序优化;

所以volatile 并非原子性操作。

 

AtomicInteger非阻塞同步(原子性CAS)

同步:多线程并发访问共享数据时,保证共享数据再同一时刻只被一个或一些线程使用。

我们知道,阻塞同步和非阻塞同步都是实现线程安全的两个保障手段,非阻塞同步对于阻塞同步而言主要解决了阻塞同步中线程阻塞和唤醒带来的性能问题,那什么叫做非阻塞同步呢?在并发环境下,某个线程对共享变量先进行操作,如果没有其他线程争用共享数据那操作就成功;如果存在数据的争用冲突,那就才去补偿措施,比如不断的重试机制,直到成功为止,因为这种乐观的并发策略不需要把线程挂起,也就把这种同步操作称为非阻塞同步(操作和冲突检测具备原子性)。在硬件指令集的发展驱动下,使得 "操作和冲突检测" 这种看起来需要多次操作的行为只需要一条处理器指令便可以完成,这些指令中就包括非常著名的CAS指令(Compare-And-Swap比较并交换)。《深入理解Java虚拟机第二版.周志明》第十三章中这样描述关于CAS机制:

图取自《深入理解Java虚拟机第二版.周志明》13.2.2
所以再返回来看AtomicInteger.incrementAndGet()方法,它的时间也比较简单

/*** Atomically increments by one the current value.** @return the updated value*/public final int incrementAndGet() {for (;;) {int current = get();int next = current + 1;if (compareAndSet(current, next))  return next;}}

incrementAndGet()方法在一个无限循环体内,不断尝试将一个比当前值大1的新值赋给自己,如果失败则说明在执行"获取-设置"操作的时已经被其它线程修改过了,于是便再次进入循环下一次操作,直到成功为止。这个便是AtomicInteger原子性的"诀窍"了,继续进源码看它的compareAndSet方法:

/*** Atomically sets the value to the given updated value* if the current value {
@code ==} the expected value.** @param expect the expected value* @param update the new value* @return true if successful. False return indicates that* the actual value was not equal to the expected value.*/public final boolean compareAndSet(int expect, int update) {  return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}

 

可以看到,compareAndSet()调用的就是Unsafe.compareAndSwapInt()方法,即Unsafe类的CAS操作。

 

转载于:https://www.cnblogs.com/jay-wu/p/10330874.html

你可能感兴趣的文章
vue用阿里云oss上传图片使用分片上传只能上传100kb以内的解决办法
查看>>
图tp delDataById问题
查看>>
[CSS3] :empty Selector
查看>>
Win10远程桌面提示你的凭据不工作的处理方法
查看>>
7. Oracle数据加载和卸载
查看>>
将网桥的配置写进去/etc/sysconfig/network-scripts/ifcfg-xxx
查看>>
一起谈.NET技术,WPF 基础到企业应用系列5——WPF千年轮回2
查看>>
D3D9 effect (hlsl)(转)
查看>>
WEB在线预览PDF
查看>>
C++枚举类型
查看>>
Windows Forms、MFC、WTL、WxWidgets、Qt、GTK综合比较
查看>>
教程-Delphi第三方控件安装卸载指南
查看>>
Swift 与 JSON 数据
查看>>
django 初试
查看>>
论文笔记之:Deep Attention Recurrent Q-Network
查看>>
Android性能优化-App后台优化
查看>>
You-Get 视频下载工具 Python命令行下载工具
查看>>
微服务拆分
查看>>
数据结构+算法 学习计划与资源
查看>>
不同技术团队的配合问题及DevOps
查看>>