5 python concurrency multithreading python-3.x
我把它作为学校作业的一部分交给了,并且标记它的人提到这部分不是线程安全的.
分配是在python中创建一个多线程套接字服务器,接受一个数字并返回该数字的Fibonacci值.我的方法是通过在每个线程之间共享字典来记忆计算.
这是代码(为了简洁起见,有错误处理和删除)
from socketserver import ThreadingMixIn, TCPServer, BaseRequestHandler
class FibonacciThreadedTCPServer(ThreadingMixIn, TCPServer):
def __init__(self, server_address):
TCPServer.__init__(self, server_address, FibonacciThreadedTCPRequestHandler, bind_and_activate=True)
#this dictionary will be shared between all Request handlers
self.fib_dict = {0: 0, 1: 1, 2: 1}
class FibonacciThreadedTCPRequestHandler(BaseRequestHandler):
def handle(self):
data = self.request.recv(1024).strip()
num = int(data)
result = self.calc_fib(self.server.fib_dict, num)
ret = bytes(str(result) + '\n', 'ascii')
self.request.sendall(ret)
@staticmethod
def calc_fib(fib_dict, n):
"""
Calculates the fibonacci value of n using a shared lookup table and a linear calculation.
"""
length = len(fib_dict)
while length <= n:
fib_dict[length] = fib_dict[length - 1] + fib_dict[length - 2]
length = len(fib_dict)
return fib_dict[n]
Run Code Online (Sandbox Code Playgroud)
我知道在calc_fib方法中同时发生了读写操作,通常这意味着代码不是线程安全的.但是在这种情况下,我认为可以证明代码将始终提供可预测的结果.
事实上,读取和写入可以同时发生,因为它不被认为是线程安全的吗?或者,如果它总是返回可靠的结果,则被认为是线程安全的.
为什么我认为此代码将始终产生可靠的结果:
在字典中发生写入之前,字典中的任何给定索引都不会发生读取.
对任何给定索引的任何后续写入都将包含与先前写入相同的编号,因此无论何时发生读/写序列,它都将始终接收相同的数据.
我通过在每个操作之间添加随机睡眠并同时向几百个线程发出请求来测试这一点,并且在我的测试期间已经返回了正确的答案.
任何想法或批评都将不胜感激.谢谢.
在这种特殊情况下,GIL应该保证您的代码安全,因为:
dict
特别需要这种保证,因为类实例和非本地范围通常使用dict
s 进行属性/名称查找,并且没有 GIL ,仅仅读取这些值就会充满危险)所以在 CPython 中,这应该没问题。但我不能对其他 Python 解释器做出任何保证;如果没有 GIL,如果它们在没有内部锁定的情况下实现它们,则完全有可能由一个线程中的写入触发的重新哈希操作可能导致另一个线程从不一致/不可用状态中dict
读取。dict