多線程使用容易出現(xiàn)重入問題疮跑,有時(shí)這種重入不易發(fā)覺,我們一起看下面這個(gè)例子:
import threading
import time
class A:
def func(self, num):
self.num = num
time.sleep(5)
return self.num
class TestThread(threading.Thread):
def __init__(self, thread_id, func):
threading.Thread.__init__(self, name='test')
self.func = func
self.thread_id = thread_id
def run(self):
num = self.func(self.thread_id)
print("線程{thread_id}:{num}".format(thread_id=self.thread_id, num=num))
a = A()
th_list = list()
for i in range(5):
th = TestThread(i, a.func)
th_list.append(th)
for i in range(5):
th_list[i].start()
for i in range(5):
th_list[i].join()
上面這個(gè)例子中凸舵,多線程類調(diào)用了一個(gè)類A的成員函數(shù)func祖娘,而這個(gè)func函數(shù)會(huì)設(shè)置A的成員變量num,將線程id傳遞給func啊奄,并且打印返回值渐苏,最終的結(jié)果如下,發(fā)現(xiàn)所有線程中打印出來的數(shù)值都是4菇夸。
線程1:4
線程0:4
線程2:4
線程3:4
線程4:4
這個(gè)的根本原因是:A只有一個(gè)實(shí)例琼富,雖然傳遞給各個(gè)線程的只是一個(gè)成員函數(shù),但這個(gè)成員函數(shù)可以設(shè)置類的成員變量, 這個(gè)成員變量因此會(huì)被多個(gè)線程操縱庄新,造成修改鞠眉。
如下面代碼的這種實(shí)現(xiàn)方式,就可以解決這個(gè)問題:
import threading
import time
class A:
def func(self, num):
self.num = num
time.sleep(5)
return self.num
class TestThread(threading.Thread):
def __init__(self, thread_id, Class):
threading.Thread.__init__(self, name='test')
a = Class()
self.func = a.func
self.thread_id = thread_id
def run(self):
num = self.func(self.thread_id)
print("線程{thread_id}:{num}".format(thread_id=self.thread_id, num=num))
th_list = list()
for i in range(5):
th = TestThread(i, A)
th_list.append(th)
for i in range(5):
th_list[i].start()
for i in range(5):
th_list[i].join()
線程0:0
線程1:1
線程3:3
線程2:2
線程4:4