python - Concurrent access to a shared resource using conditions in Threads Python
问题描述
I have the below sample pretty basic code for working with conditions in Python:
import threading
import random
import time
class Producer(threading.Thread):
"""
Produces random integers to a list
"""
def __init__(self, integers, condition):
"""
Constructor.
@param integers list of integers
@param condition condition synchronization object
"""
threading.Thread.__init__(self)
self.integers = integers
self.condition = condition
def run(self):
"""
Thread run method. Append random integers to the integers list
at random time.
"""
while True:
integer = random.randint(0, 256)
self.condition.acquire()
print 'condition acquired by %s' % self.name
self.integers.append(integer)
print '%d appended to list by %s' % (integer, self.name)
print 'condition notified by %s' % self.name
self.condition.notify()
print 'condition released by %s' % self.name
self.condition.release()
time.sleep(1)
class Consumer(threading.Thread):
"""
Consumes random integers from a list
"""
def __init__(self, integers, condition):
"""
Constructor.
@param integers list of integers
@param condition condition synchronization object
"""
threading.Thread.__init__(self)
self.integers = integers
self.condition = condition
def run(self):
"""
Thread run method. Consumes integers from list
"""
while True:
self.condition.acquire()
print 'condition acquired by %s' % self.name
while True:
if self.integers:
integer = self.integers.pop()
print '%d popped from list by %s' % (integer, self.name)
break
print 'condition wait by %s' % self.name
self.condition.wait()
print 'condition released by %s' % self.name
self.condition.release()
def main():
integers = []
condition = threading.Condition()
t1 = Producer(integers, condition)
t2 = Consumer(integers, condition)
t1.start()
t2.start()
t1.join()
t2.join()
if __name__ == '__main__':
main()
As per my understanding when the consumer calls the wait()
method it would release the condition and go into sleep.
When the producer notifies the threads after it calls notify()
it seems that neither of the consumers are reacquiring the condition before they try to pop from the integer list.
Is this not a race condition ?
解决方案
消费者在被唤醒后不需要重新获取条件,wait()
因为他们直到恢复后才释放它wait()
。
他们释放的是始终与条件相关联的锁,无论是显式还是隐式。
从文档:
条件变量总是与某种锁相关联;这可以传入或默认创建一个。[...]锁是条件对象的一部分:您不必单独跟踪它。
通过获取/释放条件以及调用wait()
resp 来隐式获取和释放锁。从中醒来。
acquire() 和 release() 方法也调用关联锁的相应方法。
[..]
wait() 方法释放锁,然后阻塞,直到另一个线程通过调用 notify() 或 notify_all() 唤醒它。一旦唤醒,wait() 重新获取锁并返回。
所以总是最多有一个线程可以持有锁,从而在任何给定的时间点安全地修改共享资源。
推荐阅读
- sql - 不能按功能使用分组
- c# - 如何在不重复代码的情况下在表单的所有 Load 事件中调用方法?
- reactjs - 如何更改输入元素中的值?(反应)
- apache-spark - Spark 如何加速 JanusGraph 的批量加载?
- r - 带 dplyr 的加权条件和
- javascript - CORS 政策问题,在本地开发中有效,但在已部署站点中无效
- c++ - 如何在 Qcombobox 中获取 Qcomplete 的文本
- azure - 尝试从 azure docker 容器连接到远程 sql 服务器时出现 Pyodbc 连接错误
- sql - 按组划分的 SQL 百分比
- windows - 从印度元音符号中删除虚线圆圈