Я думаю, этот вопрос похож на ваш. Принятый ответ был:
$user = $this->getUser();
$user->addRole('ROLE_ADMIN');
$this->get('fos_user.user_manager')->updateUser($user);
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->get('security.context')->setToken($token);
Это может не иметь ничего общего с блоком синхронизации. ConcurrentModificationException
часто возникает, когда вы изменяете коллекцию, когда вы перебираете ее элементы.
List<String> messages = ...;
for (String message : messages) {
// Prone to ConcurrentModificationException
messages.add("A COMPLETELY NEW MESSAGE");
}
Обычно при изменении динамического списка во время его итерации по нему (например, в цикле foreach) получено исключение ConcurrentModificationException. Вы можете убедиться, что вы нигде этого не делаете.
Как и в предыдущем сообщении, вы можете получить ту же проблему, если удалите запись. например,
for(String message : messages) {
if (condition(message))
messages.remove(message);
}
Другим распространенным примером является очистка карты.
Эта конкретная проблема может быть решена с помощью явного итератора.
for(Iterator<String> iter = messages.iterator(); iter.hasNext();) {
String message = iter.next();
if (condition(message))
iter.remove(); // doesn't cause a ConcurrentModificationException
}
Иногда ваше приложение может быть слишком сложным и некоторые функции могут иметь слишком много побочных эффектов. Также, возможно, другой поток действительно делает что-то не так с этим списком, и вы не можете легко найти, где именно.
Для своей собственной проблемы я написал собственную систему списков, которая делегирует другой список и, после блокировки, все другие модификации бросает ConcurrentModificationException, так что плохая инструкция по модификации будет получена на выходе с исключением. Она также может обнаружить ошибки, описанные выше.
import java.util.*; /** * Created by IntelliJ IDEA. * User: francoiscassistat * Date: 12 juin 2010 * Time: 18:20:18 * * * Lockable list, made to debug ConcurrentModificationException on Lists. * The lock can be switched on/off with setLocked(boolean). * When locked, all write access to the list or iterators gets ConcurrentModificationException. * Simple usage case : * * list.setLocked(true); * * for (Object o : list.iterator()) // now this won't get ConcurrentModificationException, the other instruction that cause this will thrown the exception * { ... } * * list.setLocked(false); */ public class LockableList<E> implements List<E> { protected class LockableListIterator implements Iterator<E> { protected Iterator<E> iterator; public LockableListIterator(Iterator<E> iterator) { this.iterator = iterator; } public boolean hasNext() { return iterator.hasNext(); } public E next() { return iterator.next(); } public void remove() { checkLock(); iterator.remove(); } } protected class LockableListListIterator implements ListIterator<E> { protected ListIterator<E> listIterator; public LockableListListIterator(ListIterator<E> listIterator) { this.listIterator = listIterator; } public boolean hasNext() { return listIterator.hasNext(); } public E next() { return listIterator.next(); } public boolean hasPrevious() { return listIterator.hasPrevious(); } public E previous() { return listIterator.previous(); } public int nextIndex() { return listIterator.nextIndex(); } public int previousIndex() { return listIterator.previousIndex(); } public void remove() { checkLock(); listIterator.remove(); } public void set(E e) { checkLock(); listIterator.set(e); } public void add(E e) { checkLock(); listIterator.add(e); } } protected class LockableListSubList implements List<E> { protected List<E> list; public LockableListSubList(List<E> list) { this.list = list; } public int size() { return list.size(); } public boolean isEmpty() { return list.isEmpty(); } public boolean contains(Object o) { return list.contains(o); } public Iterator<E> iterator() { return new LockableListIterator(list.iterator()); } public Object[] toArray() { return list.toArray(); } public <T> T[] toArray(T[] a) { return list.toArray(a); } public boolean add(E e) { checkLock(); return list.add(e); } public boolean remove(Object o) { checkLock(); return list.remove(o); } public boolean containsAll(Collection<?> c) { return list.containsAll(c); } public boolean addAll(Collection<? extends E> c) { checkLock(); return list.addAll(c); } public boolean addAll(int index, Collection<? extends E> c) { checkLock(); return list.addAll(index, c); } public boolean removeAll(Collection<?> c) { checkLock(); return list.removeAll(c); } public boolean retainAll(Collection<?> c) { checkLock(); return list.retainAll(c); } public void clear() { checkLock(); list.clear(); } @Override public boolean equals(Object o) { return list.equals(o); } @Override public int hashCode() { return list.hashCode(); } public E get(int index) { return list.get(index); } public E set(int index, E element) { checkLock(); return list.set(index, element); } public void add(int index, E element) { checkLock(); list.add(index, element); } public E remove(int index) { checkLock(); return list.remove(index); } public int indexOf(Object o) { return list.indexOf(o); } public int lastIndexOf(Object o) { return list.lastIndexOf(o); } public ListIterator<E> listIterator() { return new LockableListListIterator(list.listIterator()); } public ListIterator<E> listIterator(int index) { return new LockableListListIterator(list.listIterator(index)); } public List<E> subList(int fromIndex, int toIndex) { return new LockableListSubList(list.subList(fromIndex, toIndex)); } } protected List<E> list; protected boolean locked; public LockableList(List<E> list) { this.list = list; locked = false; } public boolean isLocked() { return locked; } public void setLocked(boolean locked) { this.locked = locked; } protected void checkLock() { if (locked) throw new ConcurrentModificationException("Locked"); } public int size() { return list.size(); } public boolean isEmpty() { return list.isEmpty(); } public boolean contains(Object o) { return list.contains(o); } public Iterator<E> iterator() { return new LockableListIterator(list.iterator()); } public Object[] toArray() { return list.toArray(); } public <T> T[] toArray(T[] a) { return list.toArray(a); } public boolean add(E e) { checkLock(); return list.add(e); } public boolean remove(Object o) { checkLock(); return list.remove(o); } public boolean containsAll(Collection<?> c) { return list.containsAll(c); } public boolean addAll(Collection<? extends E> c) { checkLock(); return list.addAll(c); } public boolean addAll(int index, Collection<? extends E> c) { checkLock(); return list.addAll(index, c); } public boolean removeAll(Collection<?> c) { checkLock(); return list.removeAll(c); } public boolean retainAll(Collection<?> c) { checkLock(); return list.retainAll(c); } public void clear() { checkLock(); list.clear(); } @Override public boolean equals(Object o) { return list.equals(o); } @Override public int hashCode() { return list.hashCode(); } public E get(int index) { return list.get(index); } public E set(int index, E element) { checkLock(); return list.set(index, element); } public void add(int index, E element) { checkLock(); list.add(index, element); } public E remove(int index) { checkLock(); return list.remove(index); } public int indexOf(Object o) { return list.indexOf(o); } public int lastIndexOf(Object o) { return list.lastIndexOf(o); } public ListIterator<E> listIterator() { return new LockableListListIterator(list.listIterator()); } public ListIterator<E> listIterator(int index) { return new LockableListListIterator(list.listIterator(index)); } public List<E> subList(int fromIndex, int toIndex) { return new LockableListSubList(list.subList(fromIndex, toIndex)); } }
Просто используйте его вот так :
List list = new LockableList(new ArrayList(...)); list.setLocked(true); for (E e : list.iterator()) { ... } list.setLocked(false);
Надеюсь, это может помочь кому-то еще.
если вам нужно удалить несколько элементов из списка. Вы можете вести другой список, подобный удаляемым элементам. И, наконец, вызвать removeAll(collection). Конечно, это не подходит для огромных данных.