【发布时间】:2017-03-02 19:38:17
【问题描述】:
我将此作为学校作业的一部分提交,标记它的人提到此部分不是线程安全的。
任务是在 python 中创建一个多线程套接字服务器,它接受一个数字并返回该数字的斐波那契值。我的方法是通过在每个线程之间共享一个字典来记忆计算。
这是代码(为了简洁起见,删除了错误处理)
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]
我了解在 calc_fib 方法中同时发生读取和写入,通常这意味着代码不是线程安全的。但是在这种情况下,我认为有可能证明代码将始终提供可预测的结果。
读取和写入可以同时发生的事实是否足以不被认为是线程安全的?或者如果它总是返回一个可靠的结果,那么它被认为是线程安全的。
为什么我认为这段代码总能产生可靠的结果:
在字典中的任何给定索引发生写入之前,永远不会发生读取。
对任何给定索引的任何后续写入都将包含与先前写入相同的数字,因此无论何时发生读/写序列,它始终会收到相同的数据。
我已经通过在每个操作之间添加随机睡眠并同时使用数百个线程发出请求来对此进行测试,并且在我的测试期间已经返回了正确的答案。
任何想法或批评将不胜感激。谢谢。
【问题讨论】:
-
当你问他们这个问题时,你的标记人说了什么?
-
我们在这个课程中可以选择让在当地公司工作的专业人士匿名标记我们的作业。不幸的是,如果不通过我老师的代理人,我不能问给它做标记的人。我希望先从 StackOverflow 社区获得一些信息。
标签: python multithreading python-3.x concurrency