并发集合(九)使用原子 arrays
当你实现一个多个线程共享一个或者多个对象的并发应用时,你就要使用像锁或者同步关键词(例如synchronized)来对他们的属性的访问进行保护,来避免并发造成的数据不一致的错误。
但是这些机制会有以下一些缺点:
死锁(dead lock):例如:当一个线程等待一个锁的时候,会被阻塞,而这个锁被其他线程占用并且永不释放。这种情况就是死锁,程序在这种情况下永远都不会往下执行。
即使只有一个线程在访问共享对象,它也要执行必要的获取锁和释放锁的代码。
CAS(compare-and-swap)操作为并发操作对象的提供更好的性能,CAS操作通过以下3个步骤来实现对变量值得修改:
获取当前内存中的变量的值 用一个新的临时变量(temporal variable)保存改变后的新值 如果当前内存中的值等于变量的旧值,则将新值赋值到当前变量;否则不进行任何操作对于这个机制,你不需要使用任何同步机制,这样你就避免了 deadlocks,也获得了更好的性能。这种机制能保证多个并发线程对一个共享变量操作做到最终一致。
Java 在原子类中实现了CAS机制。这些类提供了compareAndSet() 方法;这个方法是CAS操作的实现和其他方法的基础。
Java 中还引入了原子Array,用来实现Integer类型和Long类型数组的操作。在这个指南里,你将要学习如何使用AtomicIntegerArray 类来操作原子 arrays。
指南中的例子是在Eclipse IDE下面实现的,你也可以使用其他IDE例如NetBeans来实现:
那要怎么做呢….
按照这些步骤来实现下面的例子:
//10.声明一个常量,名为 THREADS,分配它的值为 100。创建一个有1,000个元素的 AtomicIntegerArray 对象。
//14.创建并运行 100 个线程来执行 Incrementer 任务和另外 100 个线程来执行 Decrementer 任务。把线程储存入之前创建的arrays内。
它是怎么工作的…
在这个例子里,你实现了2个不同的任务来操作 AtomicIntegerArray 对象:
Incrementer task: 这个类使用getAndIncrement()方法array里的全部元素 +1
Decrementer task: 这个类使用getAndDecrement()方法array里的全部元素 -1
在 Main 类,你创建了有1000个元素的 AtomicIntegerArray,然后你执行了100次 Incrementer 和100次 Decrementer 任务。在任务结束后,如果没有出现任何数据不一致错误,那么array的全部元素的值都为0。如果你运行这个任务,由于全部元素都是0,你只会看到程序在操控台只写了结束信息。
更多…
如今,Java仅提供了另一个原子 array类。它是 AtomicLongArray 类,与 IntegerAtomicArray 类提供了相同的方法。
这些类的一些其他有趣的方法有:
get(int i): 返回array中第i个位置上的值
set(int I, int newValue): 设置array中第i个位置上的值为newValue
参见
第六章,并发集:使用原子变量
写时复制集合 —— CopyOnWriteArrayList JUC 下面还有一个系列的类,都是 CopyOnWriteXXX ,意思是写时复制,这个究竟是怎么回事?那就以 CopyOnWriteArrayList 为切入点,一起了解写时复制是怎么回事?
线程安全的集合 日常coding,我们是不是经常用到ArrayList、HashSet、HashMap这样的集合?那你知不知道这些集合在多线程中是不安全的?
ali清英 方腾飞,花名清英,英文名kiral,并发编程网创始人,支付宝技术专家,《Java并发编程的艺术》作者。
相关文章
- java线程池和并发集合(二)
- Go-并发编程-声明和使用 channel
- Gorm-并发控制
- Java 并发集合的实现原理详解编程语言
- Java多线程–并发中集合的使用之ConcurrentHashMap详解编程语言
- Linux 下多任务并发运行的实现(linux程序同时运行)
- 入安全Redis保障并发写入安全的方法(redis如何保证并发写)
- Redis并发读取技巧:优化高频请求响应速度(redis并发读取)
- MySQL实现数据并发控制加行锁(mysql中加行锁)
- 用Redis实现高并发抽奖模式(redis高并发抽奖逻辑)
- Redis集合有效防止并发冲突(redis集合防止并发)
- Redis锁如何实现强大的并发管理(redis锁是如何实现的)
- hadoopmap-reduce中的文件并发操作