我正在学习多线程。我有下面的代码,它在 CopyOnWriteArrayList 上实现循环算法。列表总是有固定数量的元素,假设是 10。
AtomicInteger counter = new AtomicInteger(0);
Lock lock = new ReentrantLock(true);
public String get(CopyOnWriteArrayList<String> fruits) {
String next;
try {
lock.lock();
counter.compareAndSet(fruits.size(), 0);
next = fruits.get(counter.getAndIncrement());
}finally {
lock.unlock();
}
return next;
}
注意:列表仅包含 10 个元素,不超过此数量。 我认为使用 AtomicInteger 在这里是没有用的,因为我已经锁定了关键部分。 有没有办法使用 Atomicnteger 而不是锁。我正在使用锁,因为下面两行可以生成竞争条件。 counter.compareAndSet(fruits.size(), 0); Fruits.get(counter.getAndIncrement());
尝试创建线程安全计数器,用于从列表中获取元素。
我认为使用 AtomicInteger 在这里毫无用处,因为我已经这样了 锁定关键部分。
如果在锁锁定时
counter
仅被访问,那么这是正确的。 在这种情况下,与随机的其他可变 AtomicInteger
包装器相比,int
没有任何优势。
有没有办法使用 Atomicnteger 而不是 锁。我正在使用锁,因为下面两行可以生成竞争条件。 counter.compareAndSet(fruits.size(), 0); Fruits.get(counter.getAndIncrement());
更具体地说,问题是
fruits.size()
、fruits.get()
、counter.compareAndSet()
和counter.getAndIncrement()
都需要保持一致。 也就是说,为了避免尽管列表非空但 get()
失败并出现 IndexOutOfBoundsException
的可能性,您需要 fruits.size()
报告的大小不要大于 fruits.get()
时的实际大小
,并且您需要 counter
之后的 compareAndSet()
的值与 getAndIncrement()
观察到的值相同。
尝试创建用于获取元素的线程安全计数器 来自列表。
AtomicInteger
是线程安全的。 CopyOnWriteArrayList
也是如此。 这里的问题是这还不够。 因此,你错误地描述了这个问题。 并不是你需要一个线程安全的计数器,而是你需要一个线程安全的迭代get()
操作。
您可以想象使用列表的
iterator
而不是通过索引检索。 但是,这将迭代创建迭代器时的列表快照,并且它不会自动回绕,这两者都将这种方法与您的想法区分开来。
可以想象,您可以跳过锁定,而是在发生时捕获
IndexOutOfBoundsException
并从中恢复。 这比听起来更难,而且很难看,只能作为练习。
您尚未透露此内容的上下文,以便我们可以决定哪些替代方案最能达到目的,但我最好的猜测是您确实想使用锁,并且您可能会使用普通的
int
柜台。