Java并发中原子操作的实现
来源:互联网 发布:java工程师优秀简历 编辑:程序博客网 时间:2024/04/28 05:44
处理器实现原子操作
如果多个处理器同时对共享变量进行读改写(i++就是经典的读改写操作)操作,那么共享变量就会被多个处理器同时进行操作,这样读改写操作就不是原子的,所以要保证操作是原子性,则必须保证同一时刻只有一个处理器访问共享变量的内存地址。
使用总线锁定保证原子性。
处理器在总线上输出一个LOCK#信号,那么其他处理器的请求将被阻塞,此时该处理器就可以独占共享内存,从而保证只有一个处理器操作共享内存。
- 使用缓存锁定保证原子性。
总线锁把CPU和内存之间通信锁住了,这使得锁定期间,其他处理器不能操作其他内存地址的数据,所以总线锁定的开销比较大,现在多用缓存锁来代替总线锁优化。如果缓存在处理器缓存行中的内存区域在LOCK操作期间被锁定,当它执行锁操作回写内存时,处理器不在总线上声言LOCK#信号,而是修改内部的内存地址,其他处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期,如果过期,就会将该缓存行设置成无效状态,从而避免多个处理器同时修改该共享内存。
JAVA如何实现原子操作
1.使用循环CAS实现原子操作
/** * 使用CAS实现线程安全计数器 */ private void safeCount() { for (;;) { int i = atomicI.get(); boolean suc = atomicI.compareAndSet(i, ++i); if (suc) { break; } } } /** * 非线程安全计数器 */ private void count() { i++; }
可能会遇到的问题:
ABA问题。因为CAS需要在操作值的时候检查下值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。ABA问题的解决思路就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加一,那么A-B-A 就会变成1A-2B-3A。
从Java1.5开始JDK的atomic包里提供了一个类AtomicStampedReference来解决ABA问题。这个类的compareAndSet方法作用是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。
循环时间长开销大。自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。
只能保证一个共享变量的原子操作。当对一个共享变量执行操作时,我们可以使用循环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候就可以用锁,或者有一个取巧的办法,就是把多个共享变量合并成一个共享变量来操作。比如有两个共享变量i=2,j=a,合并一下ij=2a,然后用CAS来操作ij。从Java1.5开始JDK提供了AtomicReference类来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行CAS操作。
2.使用锁机制实现原子操作
锁机制保证了只有获得锁的线程能够操作锁定的内存区域。JVM内部实现了很多种锁机制,有偏向锁,轻量级锁和互斥锁,除了偏向锁,JVM实现锁的方式都用到的循环CAS,当一个线程想进入同步块的时候使用循环CAS的方式来获取锁,当它退出同步块的时候使用循环CAS释放锁。
- Java并发中原子操作的实现
- ARM体系结构中原子操作 ATOMIC 的实现
- Java中原子操作类原则
- Java中原子类的实现
- SQLITE中原子提交的实现
- java中原子变量AtomicInteger等用法
- java中原子变量AtomicInteger等用法
- Linux内核ARM构架中原子变量的底层实现研究
- Linux内核ARM构架中原子变量的底层实现研究
- Linux内核ARM构架中原子变量的底层实现研究
- Linux内核ARM构架中原子变量的底层实现研究
- Linux内核ARM构架中原子变量的底层实现研究
- Linux内核ARM构架中原子变量的底层实现研究
- Java 并发 ---原子操作的实现原理
- 说说Java中原子性,可见性与指令重排序的理解
- 嵌入式 linux下kernel代码中原子性操作atomic_t
- linux中原子操作atomic_read、atomic_set、atomic_add、atomic_sub
- 关于C11标准中原子操作,看这篇就够了!
- MyBatis xml配置文件详解
- 点击按钮出现60秒倒计时js代码
- 使用Python实现网格索引
- java string的几个函数
- [解决] Error Code: 1044. Access denied for user 'root'@'%' to database
- Java并发中原子操作的实现
- 在美国大学计算机专业都学什么?
- 创建基于opencv处理功能的动态链接库
- 栈的链表实现
- 实现简单的天气预报功能
- Java线程池ThreadPoolExecutor深度探索及源码解析
- 你不甘堕落、却又不思进取
- Ubuntu 操作mysql 基本知识
- storm的ack和fail为了保证数据能正确的被处理, 对于spout产生的每一个tuple, storm都会进行跟踪, 这里面涉及到ack/fail的处理, 如果一个tuple处理成功, 会调用s