1

以下同步代码片段是否ArrayList可以在多线程环境中工作?

class MyList {
    private final ArrayList<String> internalList = new ArrayList<String>();

    void add(String newValue) {
        synchronized (internalList) {
            internalList.add(newValue);
        }
    }

    boolean find(String match) {
        synchronized (internalList) {
            for (String value : internalList) {
                if (value.equals(match)) {
                    return true;
                }
            }
        }

        return false;
    }
}

我担心一个线程将无法看到另一个线程的更改。

4

5 回答 5

5

您的代码将工作并且是线程安全的但不是并发的。您可能需要考虑使用ConcurrentLinkedQueue或其他并发线程安全的数据结构,例如notnoopConcurrentHashMap或建议的数据结构并使用方法。CopyOnWriteArraySetcontains

class MyList {
    private final ConcurrentLinkedQueue<String> internalList = 
         new ConcurrentLinkedQueue<String>();

    void add(String newValue) {
        internalList.add(newValue);
    }

    boolean find(String match) {
        return internalList.contains(match);
    }
}
于 2010-01-06T21:54:59.500 回答
3

这应该可以工作,因为在同一个对象上进行同步会建立起先发生关系,并且保证先发生读取的写入是可见的。

有关happens-before 的详细信息,请参阅Java 语言规范第17.4.5 节。

于 2010-01-06T21:52:06.643 回答
2

它会正常工作,因为对列表的所有访问都是同步的。但是,您可以CopyOnWriteArrayList通过避免锁定来提高并发性(特别是如果您有许多线程正在执行find)。

于 2010-01-06T21:50:25.147 回答
2

List它会起作用,但更好的解决方案是通过调用创建一个Collections.synchronizedList().

于 2010-01-06T21:54:36.007 回答
0

当您通过键进行查找时,您可能需要考虑为您的数据使用 Set(Tree or Hash)。他们的方法将比您当前的 find 方法快得多。

HashSet<String> set = new HashSet<String>();
Boolean result = set.contains(match); // O(1) time
于 2010-01-07T00:45:04.513 回答