Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Синхронизация / 13 сообщений из 13, страница 1 из 1
01.02.2012, 16:28:54
    #37642220
mre
mre
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация
Всем привет.

Есть такой участок кода:
Код: java
1.
2.
3.
4.
for (User user : Model.instance.users.values())
{
     //чтение данных
}



И есть такой код в другом потоке (сокет, таймер):
Код: java
1.
users.remove(user);



Участков кода первого типа много, второго - несколько.
Соответственно, иногда возникает ошибка IllegalModificationException.
Знаю, что нужно использовать synchronized, но к какому участку кода его применить первому или второму. И как его использовать: блочно или ко всему методу, где выполняются эти участки кода?
...
Рейтинг: 0 / 0
01.02.2012, 16:36:52
    #37642235
mre
mre
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация
То есть, ошибка ConcurentModificationException.
...
Рейтинг: 0 / 0
01.02.2012, 16:37:08
    #37642238
svenom
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация
Обернут должен быть и сам цикл (весь) и операция user.remove(user). Что именно использовать для блокировки - тупо synchronized или же что-то более высокоуровневое и java.util.concurrent - сразу и не скажешь, зависит от ваших требований. Так как есть читатели/писатели, то очень напрашивается использование ReadWriteLock вместо syncronized.
...
Рейтинг: 0 / 0
01.02.2012, 16:39:18
    #37642245
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация
mre
Код: java
1.
for (User user : Model.instance.users.values())



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

mreИ есть такой код в другом потоке (сокет, таймер):
Код: java
1.
users.remove(user);


Участков кода первого типа много, второго - несколько.

В этом случае проще использовать синхронизированую коллекцию, чем синхронизировать все методы.

mreЗнаю, что нужно использовать synchronized
Можно, не значит нужно.
Тут вообще сложная ситуация. У вас итерации по этой коллекции работают в разных потоках, или все в одном?
...
Рейтинг: 0 / 0
01.02.2012, 16:48:41
    #37642259
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация
Так как в любом случае синхронизация коллекции никак не спасёт все итераторы, то нужно инкапсулировать метод values() и делать с него слепок в синхронизированом методе.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
class Model{  
  private Map users;
  public setUsers(Map users){
       //Блокируем все методы вроде remove
       this.users = Collections.synchronizedMap(users);
  }
  public Collection getUsers(){
       synchronized(users){
              //Делаем слепок текущего списка только для итераторов
              return Collections.unmodifiableCollection(users.values());
       }
  }
}



Сам remove нужно реализовать в модели. Иначе прямой доступ нарушает инкапсуляцию.
...
Рейтинг: 0 / 0
01.02.2012, 17:08:19
    #37642309
mre
mre
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация
У меня сокет-сервер для большого числа пользователей.
Когда, например, пользователь уходит из игры, я делаю remove (в таймере раз в минуту проверяю подключен ли сокет), ну а чтение в рабочем порядке по необходимости: какое-то действие пользователя, или таймер.
...
Рейтинг: 0 / 0
01.02.2012, 17:16:12
    #37642326
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация
mreУ меня сокет-сервер для большого числа пользователей.
У меня для вас плохие новости. Пока вы не освоите материал на уровне понимания Java Concurrency in Practice, у вас будет сокет-сервер для небольшого числа пользователей.

Вообще сокет-сервер это Netty и MINA. А работа с юзерами это уже бизнес-логика приложения.

mreКогда, например, пользователь уходит из игры, я делаю remove (в таймере раз в минуту проверяю подключен ли сокет), ну а чтение в рабочем порядке по необходимости: какое-то действие пользователя, или таймер.
Возможности готового сокет-сервера не позволяют отследить отключения пользователя?
...
Рейтинг: 0 / 0
01.02.2012, 17:18:01
    #37642330
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация
mreУ меня сокет-сервер для большого числа пользователей.
В этом случае лучше всеми возможными способами избегать всего что связано со словом synchronized. Начать с ReadWriteLock и не блокирующих алгоритмов.
...
Рейтинг: 0 / 0
01.02.2012, 17:22:12
    #37642344
mre
mre
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация
Ок, спасибо, а не подскажите как можно следующий код применить к моему случаю?

Код: java
1.
2.
3.
4.
5.
6.
7.
Lock l = ...;
l.lock();
try {
// доступ к защищенным ресурсам
} finally {
l.unlock();
} 
...
Рейтинг: 0 / 0
01.02.2012, 17:35:23
    #37642380
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация
mreОк, спасибо, а не подскажите как можно следующий код применить к моему случаю?
Гугл подскажет:
https://www.google.com/search?q=ReadWriteLock+example

Вам нужен именно ReadWriteLock. При использовании обычного ReentrantLock, методы чтения будут блокировть вызовы из разных потоков. Хотя читать в разных потоках безопасно и без блокировки.

Как я уже писал выше все методы доступа должны быть в модели. Все эти методы делятся на два типа - читающие и модифицирующие.
Чтение не блокирует чтение, но блокирует модификацию.
Модификация блокирует и чтение и модификации в других потоках.

Метод для итерации - getUsers() в любом случае нужно делать слепком. Пример уже привел. Это метод чтения. В нем используется readLock(). Метод remove и аналогичные нужно завернуть в блокировку через writeLock().
...
Рейтинг: 0 / 0
01.02.2012, 17:42:48
    #37642404
забыл ник
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация
Пока вы не прочитаете Java Concurrency in practice, или хотя бы Java Memory model, любые ваши попытки написать корректный многопоточный код врядли приведут к чему то хорошему. Теоретически вы сможете написать, но гарантировать его правильность - нет. Что касается вашего случая, возможно подойдет просто замена коллекции на CopyOnWriteArrayList или ConcurrentHashMap. Если не подойдет, то synchronized или reentrantLock, и поймите, когда вы спрашиваете - что у меня тут не правильно и как мне сделать - мы не видем весь ваш код, а так как основные траблы в многопоточном программировании вылазят 'иногда' и "часто в месте в котором не ждали", то другого выхода кроме как разобраться в предмете у вас нет. Если нужно кое что уточнить - пожалуйста, а теорию будьте добры изучите.
...
Рейтинг: 0 / 0
01.02.2012, 17:50:17
    #37642429
mre
mre
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация
Ясно, спасибо вам всем!
...
Рейтинг: 0 / 0
01.02.2012, 18:14:27
    #37642510
mre
mre
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация
Почитал про ConcurrentHashMap и CopyOnWriteArrayList, думаю, это как раз мне и поможет.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Синхронизация / 13 сообщений из 13, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]