Py学习  »  Python

在线程安全对象上使用包装器的python线程

Fleetscut • 5 年前 • 1263 次点击  

我开始学习在python中使用线程,我想看看如果将线程安全的对象包装在类或其他对象中,它是否仍然是安全的。

我为队列编写了一个简单的包装:

队列包装器.py

import queue
import time

class queueWrapper(object):

def __init__(self):
    self.queue = queue.Queue()

def addItem(self, id, item):
    try:
        self.queue.put(f'Item {id}:{item}')
    except:
        print('Add Error')

def getItem(self):
    try:
        item = self.queue.get()
    except:
        print('Get Error')
    else:
        self.queue.task_done()

    return item

然后我写了这个来使用它:

Me.Py

import threading
import time
from queueWrapper import *

def producer(id, q, lock):
    for i in range(10):
         # time.sleep(1)
         with lock:
             q.addItem(id, i)

         print(f'Worker {id}: Adding {i}')

def consumer(id, q, lock):
    for i in range(20):
        # time.sleep(0.1)
        with lock:
            item = q.getItem()

        if item:
            print(f'Get: Got {item}')


lock = threading.Lock()
q = queueWrapper()
producer1 = threading.Thread(target = producer, name = 'Add 1', args = {1, q, lock})
producer2 = threading.Thread(target = producer, name = 'Add 2', args = {2, q, lock})
consumer1 = threading.Thread(target = consumer, name = 'Get', args ={1, q, lock})

producer1.start()
producer2.start()
consumer1.start()

producer1.join()
producer2.join()
consumer1.join()

在我添加锁之前,我得到了下面的错误。在我添加锁之后,在某些运行中它将运行到完成,但在其他运行中它仍然会给出错误

Exception in thread Add 2:
Traceback (most recent call last):
    File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
        self.run()
    File "/usr/lib/python3.7/threading.py", line 865, in run
        self._target(*self._args, **self._kwargs)
    File "/home/fleetscut/programming/python/threads/queue_wrapper/main.py", line 9, in producer
        q.addItem(id, i)
AttributeError: 'int' object has no attribute 'addItem'

我认为这可能是由于尝试过快地添加/获取项,所以我在每个线程方法中添加了time.sleep调用,但是错误开始在所有运行中发生。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/40893
 
1263 次点击  
文章 [ 1 ]  |  最新文章 5 年前
Carcigenicate
Reply   •   1 楼
Carcigenicate    5 年前

不要使用集合来传递参数。在许多python版本中,集合是无序的。你不能保证在迭代时它们的顺序和字面的顺序是一样的。似乎是 1 q 在迭代时交换位置。我可以在我的python版本中半复制它:

q = queueWrapper()
lock = threading.Lock()

print(*{1, q, lock}) 

1 <unlocked _thread.lock object at 0xe7560830> <__main__.queueWrapper object at 0xe7552f50>

注意队列和锁是如何交换位置的。

改用列表或元组。两者都能妥善维持秩序:

producer1 = threading.Thread(target = producer, name = 'Add 1', args = (1, q, lock))