我需要锁来保护cod中的多线程竞争条件吗

2024-09-29 19:30:31 发布

您现在位置:Python中文网/ 问答频道 /正文

Jython和Jython将支持多线程。方法sendMessage用于接收来自特定客户机的消息,客户机可以向其他几个客户机发送相同的消息(这是参数receivers的作用,而{}是一个列表)。方法receiveMessage用于接收从其他客户端发送的特定客户端的消息。在

问题是我是否需要方法sendMessagereceiveMessage的锁?我认为没有必要,因为即使一个客户机X正在接收它的消息,另一个客户机Y附加到消息池以将消息传递给客户机X是完美的。我认为对于defaultdict/list,append/pop都是原子的,不需要保护。在

如果我错了,请随时纠正我。在

from collections import defaultdict

class Foo:
    def __init__(self):
        # key: receiver client ID, value: message
        self.messagePool = defaultdict(list)
    def sendMessage(self, receivers, message):
        # check valid for receivers
        for r in receivers:
            self.messagePool[r].append(message)
    def receiveMessage(self, clientID):
        result = []
        while len(self.messagePool[clientID]) > 0:
            result.append(self.messagePool[clientID].pop(0))

        return result

Tags: 方法self消息message客户机defjythonresult
3条回答

我认为这个问题对于CPython herehere来说已经得到了很好的回答(基本上,因为GIL,您是安全的,尽管文档中没有正式提到这一点(比如on defaultdictlist)。但我理解您对Jython的担心,所以让我们使用一些官方来源来解决它,比如Jython source code。一个Pythonlist就是一个javaish ^{},上面有这样的代码:

public void append(PyObject o) {
    list_append(o);
}
final synchronized void list_append(PyObject o) {
...
}
public PyObject pop(int n) {
    return list_pop(n);
}
final synchronized PyObject list_pop(int n) {
...
}

由于我们有这些方法synchronized,所以我们可以确保列表附录和pop在Jython中也是线程安全的。因此,您的代码似乎是安全的wrt线程。在

尽管Queue建议仍然有效,但它确实更适合这个用例。在

我建议使用Queue而不是list。它是为带锁的append\pop-in线程设计的。在

竞争条件是指两个或多个线程同时更改某些全局状态。在

sendMessage的代码中,您正在更改self.messagePool[r],它是一个全局对象。因此,self.messagePool[r]应该在附加新项之前锁定。在

与您的receiveMessage函数相同。在

list.appendlist.pop是O(1)和O(1)运算的铠装,因此很少会引起任何竞争条件。然而,风险仍然存在。在

相关问题 更多 >

    热门问题