这个双端队列在Python中是线程安全的吗?

发布于 2024-12-22 07:29:13 字数 995 浏览 5 评论 0原文

我无法确定以下双端队列是否是线程安全的。
简而言之,我创建了一个带有双端队列的类,该类在新线程中每 1 秒显示一次其内容(因此在打印时不会暂停主程序)。
双端队列是从主线程填充的,所以基本上应该有碰撞的机会。
然而,双端队列是使用类方法填充的,因此本质上它是从实例本身内部访问的,因此是从同一个线程访问的。
下面是简化的代码:

import threading
import time
from collections import deque

class MyQueue(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.q = deque()
        self.start()

    def run(self):
        # pop out queue items every 1 sec
        # (please ignore empty deque for now)
        while True:
            print self.q.popleft()
            time.sleep(1)

    def add_to_q(self, val):
        # this function is called from outside
        self.q.append(val)

# main
# fill the queue with values
qu = MyQueue()
for i in range(1:100):
    qu.add_to_q(i)

那么,虽然从队列中添加和删除项目是在实例内部进行的,但是从实例外部调用添加函数是否存在风险?

编辑:
由于我需要修改双端队列中的项目,因此我必须使用双端队列。我所做的是:将其旋转()到给定的项目,将其弹出,修改,将其推回原处,然后旋转()将其返回到原始位置。
除非我找到一种方法来实现修改队列中的项目,否则我将不得不坚持使用 Deque

I can't decide whether the following deque is thread-safe.
In short, I've created a class with a deque that displays its contents every 1 sec in a new thread (so it won't pause the main program while printing).
The deque is filled from the main thread, so basically there SHOULD be a chance of collision.
HOWEVER, the deque is filled using a class method, so essentially it is accessed from within the instance itself, therefore from the same thread.
Here's the simplified code:

import threading
import time
from collections import deque

class MyQueue(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.q = deque()
        self.start()

    def run(self):
        # pop out queue items every 1 sec
        # (please ignore empty deque for now)
        while True:
            print self.q.popleft()
            time.sleep(1)

    def add_to_q(self, val):
        # this function is called from outside
        self.q.append(val)

# main
# fill the queue with values
qu = MyQueue()
for i in range(1:100):
    qu.add_to_q(i)

So, although adding and removing items from queue take place inside the instance, is there a risk due to the adding function being called from outside the instance?

EDIT:
Since I need to modify items in my deque, I had to use Deque. What I do is: roatate() to the given item, pop it out, modify, push it back in and rotate() it back to its original position.
Unless I find a way of implementing modifying items in a Queue, I'll have to stick to Deque

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

红尘作伴 2024-12-29 07:29:13

双端队列是线程安全的(http://docs.python.org/library/collections .html#deque-objects) 用于从相对侧追加和弹出。 在这里,文档只提到了append()和popleft () 是线程安全的。

队列本身有一个线程安全的实现。因此,除非您有一些奇怪的要求,否则您应该使用它。

Deque is thread-safe (http://docs.python.org/library/collections.html#deque-objects) for appends and pops from opposite sides. Beneath here, the docs only mention that append() and popleft() are thread-safe.

There is a thread-safe implementation of the Queue itself. So you should be using it unless you have some strange requirements.

伪装你 2024-12-29 07:29:13

Deque 作者在这里。

MyQueue() 类对我来说看起来是正确的(至少就线程安全问题而言)。

append()popleft()方法都是原子的。

该代码确实需要 EAFP 逻辑来处理输入为空的情况:

def run(self):
    while True:
        try:
            print self.q.popleft()
        except IndexError:
            pass
        time.sleep(1)

Deque author here.

The MyQueue() class looks correct to me (at least with respect to the question of thread-safety).

The append() and popleft() methods are both atomic.

The code does need EAFP logic to handle the case where the input is empty:

def run(self):
    while True:
        try:
            print self.q.popleft()
        except IndexError:
            pass
        time.sleep(1)
痴者 2024-12-29 07:29:13

有关信息,有一个针对双端队列线程安全引用的 Python 票证 (https://bugs.python.org/issue15329)。

标题“澄清哪些双端队列方法是线程安全的”,底线是:

双端队列的append()、appendleft()、pop()、popleft()和len(d)
CPython 中的操作是线程安全的。附加方法有一个
DECREF 在末尾(对于已设置 maxlen 的情况),但这
发生在所有结构更新完成并且
不变量已经恢复了,所以处理这些操作就可以了
作为原子。

无论如何,如果您不是 100% 确定并且您更喜欢可靠性而不是性能,只需为 print self.q.popleft()self.q.append(val)< 添加一个类似的 Lock /代码>;)

For information there is a Python ticket referenced for deque thread-safety (https://bugs.python.org/issue15329).

Title "clarify which deque methods are thread-safe", bottom line is:

The deque's append(), appendleft(), pop(), popleft(), and len(d)
operations are thread-safe in CPython. The append methods have a
DECREF at the end (for cases where maxlen has been set), but this
happens after all of the structure updates have been made and the
invariants have been restored, so it is okay to treat these operations
as atomic.

Anyway, if you are not 100% sure and you prefer reliability over performance, just put a like Lock for print self.q.popleft() and self.q.append(val) ;)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文