当访问同一对象时,Python线程和全局解释器锁定



我正在尝试理解python线程及其工作方式。

从我的理解中,我知道有GIL(全局解释器锁)可以防止两个线程同时访问内存。

这是非常合理的,即使它减慢了程序。

但是下面的代码显示出意外的结果。

import thread, time
mylist = [[0,1]]
def listTo300Elem(id):
    while len(mylist) < 300:
        mylist.append([id, mylist[-1][1]+1])
thread.start_new_thread(listTo300Elem, (1,))
thread.start_new_thread(listTo300Elem, (2,))
thread.start_new_thread(listTo300Elem, (3,))
thread.start_new_thread(listTo300Elem, (4,))
thread.start_new_thread(listTo300Elem, (5,))
thread.start_new_thread(listTo300Elem, (6,))
thread.start_new_thread(listTo300Elem, (7,))
time.sleep(5)
print mylist
print len(mylist)

结果是

[[0,1],[1,2],[1,3],[1,4],[1,5],[1,6],[1,6],[1,7],[1,7],[1,8],[1,9],[1,10],[1,11],[1,12],[1,13],[1,14],[1,15],[1,15],[1,16],[1,16],[1,17],[1,18],[1,19],[1,20],[1,21],[1,22],[1,23],[1,23],[1,24],[1,25],[1,26],[1,27],[1,28],[1,29],[1,30],[1,31],[1,32],[1,33],[1,34],[1,35],[1,36],[1,37],[1,38],[1,39],[1,30],[1,40],[1,41],[1,41],[1,41],[1,42],[1,43],[1,44],[1,45],[1,46],[1,47],[1,48],[1,48],[1,49],[1,50],[1,51],[1,52],[1,53],[1,54],[1,55],[1,56],[1,57],[1,57],[1,58],[1,59],[1,60],[1,61],[1,62],[1,63],[1,64],[1,65],[1,65],[1,66],[1,66],[1,67],[1,68],[1,69],[1,70],[1,71],[1,72],[2,73],[2,73,[2,74],[2,75],[2,76],[2,77],[2,78],[2,79],[5,80],[5,81],[5,82],[5,82],[5,83],[5,84],[5,85],[5,86],[5,87],[5,88],[5,89],[5,90],[5,91],[5,91],[5,92],[5,93],[5,94],[3,95],[3,96],[3,97],[3,98],[3,99],[3,99],[3,100],[3,101],[3,102],[3,103],[3,104],[3,105],[3,106],[3,107],[3,107],[3,108],[3,109],[3,110],[3,111],[3,112],[3,113],[3,114],[3,115],[3,116],[3,116],[3,117],[7,118],[7,119],[7,120],[7,121],[7,122],[7,123],[7,123],[7,124],[2,80],[2,81],[2,82],[2,83],[2,84],[2,85],[2,86],[2,87],[2,87],[2,88],[2,89],[2,90],[2,91],[2,92],[2,93],[2,94],[2,95],[2,95],[2,96],[2,97],[2,98],[2,99],[2,100],[2,101],[2,102],[2,103],[2,103],[2,104],[2,105],[2,106],[2,107],[2,108],[2,109],[2,110],[2,111],[2,112],[2,112],[2,113],[2,114],[2,115],[2,116],[2,117],[2,118],[2,119],[2,120],[2,120],[2,121],[2,122],[2,123],[2,124],[2,125],[2,126],[2,127],[2,128],[2,128],[2,129],[2,130],[2,131],[2,132],[2,133],[2,134],[2,135],[2,136],[2,137],[2,137],[2,138],[2,139],[2,140],[2,141],[7,125],[7,126],[7,127],[7,128],[7,128],[7,129],[7,130],[7,131],[7,132],[7,133],[7,134],[7,135],[7,136],[7,137],[7,137],[7,138],[7,139],[7,140],[7,141],[7,142],[7,143],[7,144],[7,145],[7,145],[7,146],[7,147],[7,148],[7,149],[7,150],[7,151],[7,152],[7,153],[7,154],[7,154],[7,155],[7,156],[7,157],[7,158],[7,159],[7,160],[7,161],[7,161,[7,162],[7,163],[7,164],[7,165],[7,166],[7,167],[7,168],[7,169],[7,170],[7,170],[7,171],[6,172],[6,173],[6,174],[6,175],[6,176],[6,177],[6,178],[3,179],[3,179],[3,180],[3,181],[3,182],[3,183],[3,184],[3,185],[3,186],[3,187],[3,187],[3,188],[3,189],[3,190],[3,191],[3,192],[3,193],[3,194],[3,195],[3,195],[3,196],[3,197],[3,198],[3,199],[3,200],[3,201],[7,202],[7,203],[7,204],[7,204],[7,205],[7,206],[7,207],[7,208],[7,209],[1,210],[1,211],[1,211],[1,212],[1,213],[1,214],[1,215],[1,216],[1,217],[1,218],[1,219],[1,219],[1,220],[1,221],[1,222],[1,223],[1,224],[1,225],[1,226],[1,227],[1,228],[1,228],[1,229],[1,230],[1,231],[1,232],[1,233],[1,234],[1,235],[1,236],[1,237],[1,237],[1,238],[3,239],[5,240],[2,142],[6,179]304

从我的理解中,结果必须是由于吉尔的秩序,但事实并非如此。

我可以为此示例提供解释,以及更多的项目?

您期望什么?那一个线程添加一个项目,然后再添加另一个线程等。比为什么有这么多线程,如果它们一次工作?线程正在尝试与一个对象同时使用。但是,由于GIL并不是进行并行计算的好事,因此它们如此丑陋。

要获得更多的不可思议的吉尔,您可以添加记录。

logging.basicConfig(format="%(levelname)-8s [%(asctime)s] %(threadName)-12s %(message)s", level=logging.DEBUG, filename='log.log')
def listTo300Elem(id):
    list_len = len(mylist)
    while list_len < 300:
        item = mylist[-1][1]+1]
        mylist.append([id, item])
        logging.debug('Len = {}, item {} added'.format(list_len, item))
        list_len = len(mylist)
    logging.debug('Len = {}, exit'.format(list_len, item))

因此,python中的线程不适合所有情况。

最新更新