[python] multithreading & mutable sequence types

Marek Schmidt xschmi01 na stud.fit.vutbr.cz
Pondělí Říjen 25 14:13:40 CEST 2004


Radek Kanovsky wrote:
> On Mon, Oct 25, 2004 at 11:02:52AM +0200, Marek Schmidt wrote:
> 
> 
>>Dobrý den,
>>
>>s Pythonem teprve začínám a tak ještě nejsem příliž zběhlý v hledání 
>>odpovědí na otázky... snažil jsem se... :-)
>>
>>Jsou operace s pythonovským seznamem thread-safe?
> 
> 
> Obecne nejsou zadne operace v pythonu thread-safe, ale konkretne append
> a pop nad seznamem jo, protoze jsou implementovane v C a behem jejich
> vykonavani je zamceny Global Interpreter Lock (GIL) a nikdo druhy by
> nemel mit sanci neco s tim seznamem udelat. Funkce/metody psane v C
> mohou GIL explicitne odemknout, pokud na neco cekaji (typicky na I/O),
> ale tyto dve to nedelaji. Nicmene asi neni dobre na to spolehat a navic
> to urcite plati jenom CPythonu. Jython, IronPython a dalsi odrudy se
> mohou chovat odlisne (neznam).
> 
> 
>>Potřebuji udělat něco takového:
>>
>>class KnightWhoSayNi(threading.Thread):
>>  def __init__(self):
>>    ...
>>    self.semafor = threading.Semaphore(0)
>>    self.queue = []
>>
>>  def queueSayNi(self, target):
>>    self.queue.append(target)
>>    self.semafor.release()
>>
>>  def run(self):
>>    while True:
>>       self.semafor.acquire()
>>       target = self.queue.pop(0)
>>
>>       sayNiToTarget(target)
>>
>>
>>queueSayNi se bude volat z jiných threadů. Můj dotaz pochopitelně zní: 
>>Je bezpečné to udělat takto a nebo je nutné operace s queue uzavřít mezi 
>>lock.acquire a lock.release? (případně, nejde to vše udělat nějak úplně 
>>jinak a lépe? :-)
> 
> 
> Ja bych na tohle pouzil asi threading.Condition. Moc se mne nelibi
> ono acquire/release v ruznych metodach.
>     
>     [...]
> 
>     def __init__ (self) :
>         ....
>         self.cond = threading.Condition()
>         self.queue = []
> 
>     def queueSayNi(self, target):
>         self.cond.acquire()
>         self.queue.append(target)
>         self.cond.notify()
>         self.cond.release()
>  
>     def run(self):
>         while True:
>             self.cond.acquire()
>             while not self.queue :
>                 self.cond.wait()
>             target = self.queue.pop(0)
>             self.cond.release()
>             sayNiToTarget(target)
> 
> 
> Pokud je seznam prazdny, odemce cond.wait() zamek a ceka na cond.notify().
> cond.notify() je volano po vlozeni noveho prvku a to vzbudi cekajici
> cond.wait(). Po navratu z cond.wait() je zamek opet zamceny.

Aha! Tak takhle se da pouzit Condition.. diky moc!

> Ni! Ni! Ni! Ni! Ni! Ni!

Od ted je to KnightWhoTillRecentlySaidNi
> RadekK



Další informace o konferenci Python