同步方法中的并发修改异常

时间:2012-11-01 11:19:53

标签: java multithreading synchronization

我对我的多线程程序进行了一些修改,并开始在对象的ConcurrentModificationException上获取HashTable,因此我将对HashTable的所有访问权限转换为synchronised方法避免并发访问我的对象,不像我期望的那样它没有解决问题。以下是所用设计的概述:

首先我有一个JTable显示一些usb设备的数据,这个JTable要求一个实现Observer的通信核心对象(读写的那个)数据到我的设备)通过Observable对象得到它想要的数据,它想要的数据取决于显示哪些行,以便在用户滚动de table时更新,而不是通信核心对象通过{{获取此通知1}}调用其他synchronized update方法的方法,该方法更新synchronized,保存后使用的最后读取值(此通信类在读取值时通知我的HashTable类和其他对象虽然其他JTable对象)。在更新Observable时,最后一种方法出现异常。这是代码的简化:

以下方法属于通信核心对象

HashTable

我需要这种方法,因为我有多个窗口要求来自usb设备的值,并且这个通信对象负责处理,在我添加最后一个值的public synchronized void update(Observable o, Object arg) { // do some other work // calls the second synchronized method updateMonitorList(); } private synchronized void updateMonitorList() { // updates a list of monitoring addresses (no problem here) // m_lastValues is the HashTable that is giving me headaches Iterator<Parameter> itr = m_lastValues.keySet().iterator(); while (itr.hasNext()) { // removes the currently not used parameters from the HashTable Parameter p = itr.next(); // concurrent exception here WHY? :/ boolean contains = false; for (int i = 0; i < m_monitorList.size(); i++) { if (p.equals(m_monitorList.get(i))) { contains = true; break; } } if (!contains) { m_lastValues.remove(p); } } // more operations with the HashTable for (int i = 0; i < m_monitorList.size(); i++) { // adds newly added parameters to the hashtable boolean contains = false; for (Observer key : m_requestedParameters.keySet()) { if (key.equals(m_monitorList.get(i))) { contains = true; break; } } if (!contains) { m_lastValues.put(m_monitorList.getAt(i), m_monitorList.getAt(i).m_intUserSetting); } } } // this method is used to know if a value has changed private synchronized boolean getParameterChanged(Parameter currentParamer) { Integer v = m_lastValues.get(currentParamer); return v == null || v != currentParamer.m_intUserSetting; } 之前,并发没有问题。 HashTable m_lastValues未在上面未列出的任何其他方法中使用。

有什么建议吗?提前谢谢。

[编辑]

实际上这不是一个多线程问题,它只是一个被误解的异常含义。正如@Tudor所指出的那样,问题是HashTable循环中的remove()方法。以下是我解决它的方法:

此代码进入while方法,请注意updateMonitorList()(第一个问题是no Iterator was needed循环),实际上for没有区别:< / p>

Iterator

1 个答案:

答案 0 :(得分:12)

for (Parameter key : m_lastValues.keySet()) // exception this line
{
    // removes the currently not used parameters from the HashTable
}

问题出在这里。无论同步如何,您都无法在迭代时更改集合。实际上这是一个单线程问题。

您可以做的是切换到explicit iterator并使用remove()或保存要在单独的集合中删除的项目,然后将其删除。

Iterator<Parameter> iter = m_lastValues.keySet().iterator();
while (iter.hasNext()) {
    Parameter current = iter.next();
    for (int i = 0; i < m_monitorList.size(); i++) {
        if(current.equals(m_monitorList.get(i)) {
            iter.remove();
            break;
        }
    }
}