31-运用原子性数组
7.9 运用原子性数组
考虑到实现一个并发应用程序时至少会有一个对象共享于几个线程。在这种场景下,就必须使用同步机制来对共享对象的字段进行访问保护(例如锁或关键字 synchronized
),以此来避免数据不一致的问题。
但这些机制有如下问题。
- 死锁:出现该情况是由于一个线程为了等待一个锁而被阻塞,但持有该锁的其他线程永不释放它。在这种情况下,这会阻塞程序以致它永远不会执行完成。
- 如果只有一个线程访问该共享对象,则它必须执行必要的代码来获取和释放锁。
为了在这些情况下能提供更好的性能,Java开发了 compare-and-swap 操作。该操作采用如下步骤来修改变量的值。
1.先获取变量的旧值。
2.把变量的值变更为一个临时变量的新值。
3.如果旧值与变量的实际值相等,则替换旧值为新值。如果其他线程已经改变该旧值,则它可能与实际值不一致。
在这种机制下,就不需要同步机制了,因此这可以避免死锁并且获得更好的性能。但该机制也有缺陷。该操作必须从任何边际效应中释放出来,因为它们可能会通过高度满足资源的活锁来进行重试。与标准锁进行对比,对于性能来说,它们通常也更难监控。
Java在 原子性变量 中实现了这种机制。这些变量提供了 compareAndSet()
方法(它具备compare-and-swap操作实现)和其他方法。
Java还提供 原子性数组 ,以允许原子性操作整型和长整型数值的数组。在本节,将会学习如何使用 AtomicIntegerArray
类来操作原子性数组。考虑到如果用的是 AtomicInteger[]
,则它并非是线程安全的对象。一个独立的 AtomicInteger
对象是线程安全的,但其数组形式的数据结构则不是。