我正在尝试读取1GB文件,将其分成4MB文件,然后使用多个线程单独上传。但是,我不认为我正确地传递了“块”对象。我怀疑这一行可能不正确:
threading.Thread(target=UploadFile, args=[filename, chunk]).start()
在将其作为参数传递之前,是否需要复制“chunk”?我担心的是“chunk”在这个例子中不是线程安全的,因此,上传的块与源数据不一致。
以下是完整的方法:
def ChunkAndUpload(inputFilename):
global runningThreadCount
maxThreads = 10
chunkSize = 1024*1024*4
index = 0
with open(inputFilename, "rb") as f:
while True:
chunk = f.read(chunkSize)
if not chunk: break
filename = str(index) + ".dat"
while (True):
if (runningThreadCount<maxThreads):
runningThreadCount += 1
threading.Thread(target=UploadFile, args=[filename, chunk]).start()
break
else:
sleep(.1)
index+=1
谢谢!
答案 0 :(得分:4)
bytes
是一个不可变类型(就像str
一样)。不可变类型不受竞争条件的影响(除非您可以使用对完全不同的对象的引用来完全替换共享名称)。
一旦args=[filename, chunk]
,您就制作了一个新的list
,其中“恰巧”包含与bytes
相同的chunk
的引用;从那一刻起,chunk
可以重新分配,无论list
是否成功发布,它都不会影响Thread
的内容。
答案 1 :(得分:3)
即使通过引用新线程传递参数(因此更改为块将显示在另一个线程中),您的代码也不会写到块字节数组,它只需要参考每次从f.read
到新的字节对象。因此,您似乎应该是安全的,但如果上传速度足够慢,您可能会立即将整个文件读入内存。