1 回答
TA贡献1802条经验 获得超5个赞
您的同步有问题。
您使用的同步将使用“this”锁进行同步。你可以这样想象:
public synchronized void foo() { ... }
是相同的
public void foo() {
synchronized(this) {
....
}
}
这意味着,在进入之前,当前 Thread 将尝试获取“这个对象”作为锁。现在,如果你有一个工作线程,它也有一个同步方法(用于向表中添加内容),它们不会完全相互排斥。你想要的是,在下一个线程开始工作之前,一个线程必须完成他的工作。
第一个是 Hashtable,它会导致程序崩溃并抛出未知的 ConcurrencyIssue。
之所以会出现这个问题,是因为它可能会发生,即 2 个线程同时调用某些东西。为了说明这一点,想象一个线程对其调用 put(key, value) 和另一个线程调用 remove(key)。如果这些调用同时执行(例如由不同的内核执行),那么生成的 HashTable 会是什么?因为没有人可以肯定,所以会抛出ConcurrentModificationException。注意:这是一个非常简单的解释!
当我使用 ConcurrentHashMap 时,数据是错误的,因为它没有在下一个对象与 ConcurrentHashmap 进行比较之前及时删除条目
ConcurrentHashMap 是一个实用程序,为了避免并发问题,它不是神奇的,多功能的,独角兽狩猎,黄油刀。它同步了 mehtod 调用,这导致只有一个线程可以在 HashMap 上添加或删除或执行任何其他工作。它不具有与某种锁相同的功能,这将导致对分配给线程的映射的访问。
可能有一个想要调用 add 的线程和一个想要调用 remove 的线程。ConcurrentHashMap 仅限制了这些调用,它们不能同时发生。哪个先来?你有权力(在这种情况下)。你想要的是,一个线程必须完成他的工作,然后下一个线程才能完成它的工作。
你真正需要什么取决于你。在java.util.concurrent包带来的,你可以使用类整体阿森纳。例如:
您可以为每个 Map使用一个锁。有了这个,每个线程(排序/删除/添加或其他)可以首先获取所述 Map 的锁,然后在该 Map 上工作,如下所示:
public Worker implements Runnable {
private int idOfMap = ...;
@Override
public void run() {
Lock lock = getLock(idOfMap);
try {
lock.lock();
// The work goes here
//...
} finally {
lock.unlock();
}
}
}
行 lock.lock() 将确保在方法调用返回后没有其他线程正在处理 Map 并修改它,因此该线程将具有对 Map 的双向访问权。在您完成删除正确的元素之前,没有一种排序。
当然,您必须以某种方式持有所述锁,就像在数据对象中一样。话虽如此,您还可以在每个线程中使用信号量、synchronized(map) 或以 Runnables 的形式在 Map 上制定您的工作,并将它们传递给另一个线程,该线程一个接一个地调用他收到的所有 Runnables。可能性几乎是无限的。我个人建议从锁定开始。
添加回答
举报