LINUX.ORG.RU

Java synchronized keyword

 concurrent,


0

1

Есть у меня android приложение которое рисует объекты в отдельном потоке исполнения. Тред рисования обходит коллекцию и рисует каждый входящий в нее объект. В это время другой поток может добавлять в данную коллекцию объекты. При рисовании поток получает ссылку на коллекцию, оббегает и рисует в synchrionized блоке. В это вермя другой поток получает также ссылку на данную коллекцию, также в synchronized блоке по ссылке на коллекцию дабавляет в нее объект. При этом я все равно получаю concurrent modification exception. Причину вижу в это что это две разные ссылки на один и тот же объект в памяти. Прав ли я? Если так, то чтобы это поправить мне каждый раз нужно работать с одной и той же ссылкой, так?

★★

Это же разные блоки, они друг на друга не влияют.

А почему не хочешь использовать потокобезопасные коллекции?

Hater ★★
()

Причину вижу в это что это две разные ссылки на один и тот же объект в памяти.

Синхронизация происходит не по ссылкам, а по инстансам объектов, так что не прав.

Hater ★★
()

Потому что у тебя в цикле, который оббегает коллекцию, есть где-то удаление из неё же, из-за чего итератор становится невалидным.

Почему бы перед таким оббеганием не делать теневую копию через .clone(), а потом уже бегать?

Adonai ★★★
()
Ответ на: комментарий от Adonai

есть где-то удаление из неё же

удаления нет вообще нигде в коде, только в одном месте добавление, в одном рисование объектов из коллекции + плюс еще в одном изменение свойств объектов (координат)

mio ★★
() автор топика

К черту слова, покажите код.

ya-betmen ★★★★★
()

synchronized { .. } аналогично synchronized (this) { ... }

synchronized (obj) - синхронизируется конкретно по данному объекту. Т.е. если у тебя 500 потоков, которые синхронизируются по этому объекту, то выполняться в данном блоке кода будет только один поток, остальные будут ждать.

Подозреваю, в твоём случае obj разные, т.е. синхронизация идёт на разных объектах.

Legioner ★★★★★
()
Ответ на: комментарий от mio

интересно, а на какой джаве пишешь тогда?

ii8_ ★★★★
()
Ответ на: комментарий от Legioner

Поддерживаю

рисует в synchrionized блоке

не говорит ничего про объект синхронизации, потому требую показать код.

ya-betmen ★★★★★
()
Ответ на: комментарий от ya-betmen

не говорит ничего про объект синхронизации

Что-то типа такого:

public void draw(Canvas canvas) {		        
        List ships = Game.instance().getSpaceShips();
        
        synchronized( ships ) {
	        for ( Object ship : ships ){
	        	(( Ship )ship ).draw(canvas);
	        }            		
        }
}

 public void addShip( Ship ship ) {
        List ships = Game.instance().getSpaceShips();
        
        synchronized( ships ) {
	    	ships.add(ship);	    	
        }
}
mio ★★
() автор топика
Ответ на: комментарий от mio

Может быть у тебя addShip вызывается из draw (в общем внутри цикла), т.е. не в другом потоке, а в том же самом, но во время обхода? Тогда тоже будет ConcurrentModificationException.

Конкретно этот код вполне нормальный и всё должно работать как положено. Изучи стектрейс исключения, может быть что-нибудь натолкнёт на мысль.

Legioner ★★★★★
()
Ответ на: комментарий от mio

Ну говорю же, загоняй потокобезопасные коллекции, например CopyOnWriteArrayList. Цитирую:

The «snapshot» style iterator method uses a reference to the state of the array at the point that the iterator was created. This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException. The iterator will not reflect additions, removals, or changes to the list since the iterator was created.

В твоём случае что доктор прописал. Ну либо переосмыслить логику работы приложения.

Hater ★★
()
Ответ на: комментарий от mio

Ошибка в том, что ты не понимаешь чего такое ООП. Вообще get методы плохи, а в твоём случае очень плохи - кто хочет, где хочет, делает со статическим объектом, что хочет и концов ты не найдёшь. В любом проекты сложнее hello world, ты будешь бороться с такими ошибками постоянно.

getSpaceShips может вернуть максимум unmodified Collections (что тоже плохо). А по хорошему вернуть объект реализующий поведение кораблей и там в объекте уже херачь synchronized блоки и всё что душе угодно.

vtVitus ★★★★★
()
Ответ на: комментарий от mio

Учитывая общую кошмарность кода, могу предположить, что проблема лежит в методах instance(), getSpaceShips(), draw().

Поддерживаю рекомендацию по использованию потокобезопасных коллекций, у вас явно не хватает опыта писать синхронизацию руками.

ya-betmen ★★★★★
()

Вкурсе, что рисование должно работать в Gui потоке? Логику можно вынести в поток и дергать из основного потока с помощью synchronized функции

pozitiffcat ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.