Вопрос параллелизма Java - синхронизация в коллекции - PullRequest
1 голос
/ 07 января 2010

Будет ли следующий фрагмент кода синхронизированной 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;
    }
}

Я обеспокоен тем, что один поток не сможет увидеть изменения другого потока.

Ответы [ 5 ]

5 голосов
/ 07 января 2010

Ваш код будет работать и является потокобезопасным, но не параллельным. Вы можете рассмотреть возможность использования ConcurrentLinkedQueue или других параллельных потоково-безопасных структур данных, таких как ConcurrentHashMap или CopyOnWriteArraySet, предложенных notnoop, и использовать метод contains.

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);
    }
}
3 голосов
/ 07 января 2010

Это должно сработать, потому что синхронизация на одном и том же объекте устанавливает отношение «происходит до» и записывает, что чтения «до» гарантированно будут видимыми.

См. Спецификация языка Java, раздел 17.4.5 для подробностей о том, что происходит раньше.

2 голосов
/ 07 января 2010

Это будет работать, но лучшим решением будет создать List, вызвав Collections.synchronizedList().

2 голосов
/ 07 января 2010

Будет работать нормально, потому что весь доступ к списку синхронизирован. Однако вы можете использовать CopyOnWriteArrayList для улучшения параллелизма, избегая блокировок (особенно если у вас много потоков, выполняющих find).

0 голосов
/ 07 января 2010

Возможно, вы захотите использовать Set (дерево или хэш) для своих данных, когда вы выполняете поиск по ключу. У них есть методы, которые будут намного быстрее, чем ваш текущий метод поиска.

HashSet<String> set = new HashSet<String>();
Boolean result = set.contains(match); // O(1) time
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...