Уведомления

Группа в Telegram: @pythonsu

#1 Май 8, 2015 12:35:03

jor77
Зарегистрирован: 2014-06-29
Сообщения: 16
Репутация: +  0  -
Профиль   Отправить e-mail  

Блокировка изменения переменной

Добрый день, уважаемые!

Вопрос в следующем:
Есть некая переменная, словарь. К ней имеют доступ разные функции. Все работает в многопоточном режиме. Эти все функции могут добавлять в переменную данные, изменять их, но не удалять ключи. Пусть добавляют и меняют - это нормально. Но вот в один прекрасный момент, пользователь может решить - не нужен мне какой-то ключ, или вообще все данные в словаре. и жмет кнопку “Удалить.”.
Но в момент нажатия с этой переменной могут работать несколько потоков, и, соответственно, все рухнет.

Подскажите, пожалуйста, как правильно и какими методами лучше обработать данную ситуацию? Я так понимаю, что лучше всего дождаться, пока выполнятся все потоки и тогда все удалять. Но вот, не понимаю пока как это нормально реализовать. Да, и еще ж возникнуть может такое, что переменная будет нарасхват и момент, когда она освободится может долго не возникнуть.

Офлайн

#2 Май 8, 2015 14:51:34

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2843
Репутация: +  186  -
Профиль   Отправить e-mail  

Блокировка изменения переменной

Не переживай. Из-за GIL в один и тот же момент времени может работать только 1 поток, по этому ничего у тебя не рухнет.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#3 Май 8, 2015 15:02:36

jor77
Зарегистрирован: 2014-06-29
Сообщения: 16
Репутация: +  0  -
Профиль   Отправить e-mail  

Блокировка изменения переменной

Хммм. Почему же? Очень даже рухнет. Если начать перебирать элементы словаря в одном потоке, а в другом потоке удалить элементы этого словаря - итерация срочно нарушится и упадет по RuntimeError.
Можно, конечно, обрабатывать эти исключения в каждом потоке, но может есть более красивое решение.

Офлайн

#4 Май 8, 2015 16:27:07

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2843
Репутация: +  186  -
Профиль   Отправить e-mail  

Блокировка изменения переменной

Насколько помню RuntimeError не будет ибо данные в итерируемом объекте могут меняться во время итерации. На всякий случай итерируй копию списка.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#5 Май 8, 2015 20:46:50

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Блокировка изменения переменной

1. Есть “красивые” решения: локи, мютексы, семафоры, потокобезопасные очереди, чистые функции… .
Вы похоже ищете царский путь но не в математику а в многопоточные приложения.
2. Не забывайте объекты питона никуда не денутся если вы их просто из словаря удалите, на то и есть счетчики ссылок.
3. Вы и в одном треде получите бяку если возьмете итератор а перед его использованием поудаляете некоторые элементы. Это проблема не многопоточности а вашего алгоритма.



Офлайн

#6 Май 8, 2015 21:57:42

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2843
Репутация: +  186  -
Профиль   Отправить e-mail  

Блокировка изменения переменной

> Вы и в одном треде получите бяку если возьмете итератор а перед его использованием поудаляете некоторые элементы.

Гы?

>>> s = range(10)
>>> s
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> for i, x in enumerate(s):
	del s[i+1]
>>> s
[0, 2, 4, 6, 8]



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#7 Май 8, 2015 22:29:38

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Блокировка изменения переменной

Гы?

a=dict([(i,i) for i in range(5)])
for i in a:
    a[i+100]=i+100
>>> 
Traceback (most recent call last):
  File "<editor selection>", line 2, in <module>
RuntimeError: dictionary changed size during iteration



Офлайн

#8 Май 8, 2015 22:51:06

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2843
Репутация: +  186  -
Профиль   Отправить e-mail  

Блокировка изменения переменной

> Гы?

Это потому что вы просто не знайте толк в извращениях!

a = dict([(i,i) for i in range(5)])
for k, v in a.items():
	a[k+100]=v+100



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#9 Май 8, 2015 23:02:23

jor77
Зарегистрирован: 2014-06-29
Сообщения: 16
Репутация: +  0  -
Профиль   Отправить e-mail  

Блокировка изменения переменной

Зачем такие сложности?

a = {'a':1,'b':2}
for key in a:
del a['b']

Traceback (most recent call last):
File "<string>", line 420, in run_nodebug
File "<модуль1>", line 20, in <module>
File "<модуль1>", line 14, in main
RuntimeError: dictionary changed size during iteration

doza_and
1. Есть “красивые” решения: локи, мютексы, семафоры, потокобезопасные очереди, чистые функции… .
Я знаю, что есть, но я пока не очень в этом всем силен. Я не понимаю как это применить в моей ситуации. Можно сделать Event, и ожидать его в функции удаления. При установке этого события - другим событием заблокировать выполнение всех других потоков до тех пор, пока не выполнится функция удаления. Но это пройдет, если поток один, а если несколько - это или кучу событий делать и их всех по очереди сразу ожидать, что совсем некрасиво и по-дурацки, или делать какой-то счетчик, который будет считать количество event.clear() и разрешать делать event.set() только когда все отработают, то есть счетчик обнулится. Такой вариант у меня работает. Но не нравится он мне. И не годится он в случае, когда потоки постоянно работают и могут долго не отпускать такую блокировку (если вообще отпускать)
doza_and
2. Не забывайте объекты питона никуда не денутся если вы их просто из словаря удалите, на то и есть счетчики ссылок.
Пока не понимаю что Вы имеете ввиду.

Отредактировано jor77 (Май 8, 2015 23:04:28)

Офлайн

#10 Май 9, 2015 09:52:35

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Блокировка изменения переменной

Не сильны учитесь. У вас простой случай. Словарик - разделяемый ресурс. Создаете лок и все операции со словарем осуществляете только после захвата этого лока. Будет тормозить, тогда и будете разбираться как быть дальше. Не исключено что данная реализация будет работать дольше чем однопоточная. Начинать лучше с продуманого технического задания. Делать приложение многопоточным только после обоснования необходимости многопоточности.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version