我的程序有100个帖子。
每个线程都这样做:
1)如果arrayList为空,则添加具有某些属性的元素
2)如果arrayList不为空,则遍历在arrayList中找到的元素,如果找到合适的元素(匹配某些属性),则获取它并删除arrayList
这里的问题是,当一个线程迭代通过arrayList时,其他99个线程正在等待arrayList上的锁。
如果我希望所有100个线程都能在无锁状态下工作,您会向我建议什么?所以他们都有工作要做?
由于
答案 0 :(得分:2)
您是否看过shared vs exclusive锁定?您可以在列表中使用共享锁,然后在列表元素上使用“已删除”属性。用于检查列表元素的谓词需要确保除了您拥有的任何其他查询之外,该元素未标记为“已删除” - 由于潜在的读写冲突,您需要锁定每个元素,因为遍历。然后定期获取列表上的独占锁以执行实际删除。
读锁可以在列表中实现大量并发。列表中每个元素的独占锁定不是很好,但是你需要强制内存模型更新每个线程的“已删除”标志,所以没有办法解决这个问题。
答案 1 :(得分:2)
首先,如果您没有在具有64个核心或更多核心的计算机上运行,那么您的100个线程本身就可能是一种性能损失。
然后,你所描述的ArrayList肯定不是一个好选择,因为删除一个元素不在分摊的常量时间内运行,但是在线性时间O(n)。所以这是第二次表现。您可能希望使用LinkedList而不是ArrayList(如果您坚持使用List)。
当然,我当然怀疑每次需要找到一个元素时需要遍历完整列表:不会有其他数据结构更合适吗?也许您放入列表中的元素具有“相等”的概念,因此可以使用具有O(1)查找时间的Map来代替?
这只是一个开始:正如我向您展示的那样,您所描述的内容中至少存在两个严重的性能问题......如果您需要更多帮助,也许应该澄清您的问题。
答案 2 :(得分:1)
如果您的“合适元素(匹配某些属性)”的概念可以使用Comparator
进行编码,则PriorityBlockingQueue
将允许每个线程轮询队列,无需搜索即可获取下一个元素如果队列为空,则列表或将新元素排入队列。
附录:Thilo提出一个要点:随着您的方法的发展,您可能需要根据经验确定最佳线程数。
答案 3 :(得分:0)
关键是在实际需要时仅使用arraylist上的对象锁定。
一个好主意是将arraylist子类化,并在单个读取+写入+删除过程中提供同步。
这将确保锁定的精细粒度,同时允许线程在阵列列表中运行,同时保护arraylist的语义。
答案 4 :(得分:0)
让一个线程拥有该数组并负责添加它并迭代它以找到要做的工作。找到工作单元后,将工作放在BlockingQueue上。让所有工作线程都使用take()从队列中删除工作。
这允许每次通过数组发现多个工作单元,并且可以相当有效地将它们切换到等待工作线程。