当我们使用内置队列之一(例如 ConcurrentLinkedQueue 甚至某些 BlockingQueue)时,单个调用是原子的,并且保证是线程安全的。 但是,在对 API 的 5 次调用中,有 4 次调用是单一调用,但其中一次调用的形式为:
if(some condition)
{
queue.call();
}
此调用需要位于同步块(synchronized block)中,因为此操作是非原子的。 但是不引入这个调用是否也意味着从现在开始对这个队列的所有访问,无论是读还是写都应该同步?
如果是,我是否可以假设一旦代码中出现单个非原子调用(这很可能),那么对花式队列的所有访问都必须手动同步?
最佳答案
ConcurrentLinkedQueue
并没有做出与您假设的完全相同的原子保证。来自javadoc:
Memory consistency effects: As with other concurrent collections, actions in a thread prior to placing an object into a ConcurrentLinkedQueue happen-before actions subsequent to the access or removal of that element from the ConcurrentLinkedQueue in another thread.
这与包装 LinkedList
或 Collections.synchronizedList
中的内容不同;例如,不同的线程可能会看到 size()
的不同答案,因为它不会锁定集合。
根据您的评论,您可能可以通过对 Queue
的 poll
的一次调用来替换 if 语句,并检查检索到的元素是否为 null。
关于java - 使用 ConcurrentLinkedQueue 进行一些非原子操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10294210/