实战:python 找错

n个线程协同计算1+2+…+100,例如n=2时,
第一个线程计算1+2+…+50,
第二个线程计算51+52+…+100。
最后主线程相加子线程结果输出。
这里想写复杂一点,写成start end

import threading
import math

total = 0
end = 0
start = 0
def threadnum(startl, endl, num_thread):
    global end
    global start
    print "start.... %s" % start
    print "end.... %s" %end
    num_thread = int(num_thread)
    if num_thread < 0:
        num_thread = 1

    start =  startl 
    print "start: %s" % start
    
    end = end + int(math.ceil(endl / num_thread))
    print "end: %s" % end
 
    if end > endl:
        end = endl
        print "超过目标,纠正end取值: %s" % end   
    for i in range(start,end+1):
        #print i
        global total
        total += i
        print total
 
if __name__ == "__main__":
    print "请输入线程个数:"
    num = input()
    print "请输入开始值:"
    start = input()
    print "请输入结束值:"
    end = input()
    
    for n in xrange(1, num + 1):
        thd = threading.Thread(target=threadnum,args=(start, end, num,))
        thd.start()
        thd.join()
        print "进行到第{}个thread了".format(n)
    print "all end, thanks"

看了上述代码以后,有什么疑问吗,此处共有几处错误,下面一一列出来
1、def的函数是一个线程,在线程里做各种计算处理是非常不明智的,所以应该把在函数里的计算移到外面来计算,要移除以下代码:

 start =  startl 
    print "start: %s" % start
    
    end = end + int(math.ceil(endl / num_thread))
    print "end: %s" % end
 
    if end > endl:
        end = endl
        print "超过目标,纠正end取值: %s" % end   

2、赋值问题,这段代码觉得都置为0了,为什么打印出来不是0,0呢,而是输入的值。问题原因就在于,前面这段是赋值了,并且还global,但是开始的0,0赋值跟下面的main函数是在一个作用域,后面的输入input已经将0,0覆盖了,所以无法使用0,0了。

total = 0
end = 0
start = 0
def threadnum(startl, endl, num_thread):
    global end
    global start
    print "start.... %s" % start
    print "end.... %s" %end
if __name__ == "__main__":
    print "请输入线程个数:"
    num = input()
    print "请输入开始值:"
    start = input()
    print "请输入结束值:"
    end = input()

解决办法就是把main函数的输入也放到另外一个def中去,再在main中调用输入,这样作用域就不会相互影响了,比如
def main():
print "请输入线程个数:"
num = input()
print "请输入开始值:"
start = input()
print "请输入结束值:"
end = input()
再在主函数中调用main()即可。
3、本来是N个线程协同计算,但是目前的写的是单线程的,一个线程完了,join再另外一个线程。
所以应该把join去掉或者换一个位置。
4、改成多线程以后就会面临另外一个问题,就是线程锁,total += i,这句在汇编里面是分成好几句来实现的,这样就会面临两个线程同时调用total的时候,有时候total还没有赋值完,另外一个函数就调用了,导致不同步,所以需要加线程锁。

正确解答

# _*_ coding=utf8 _*_
import threading
import math
'''
n个线程协同计算1+2+…+100,例如n=2时,
第一个线程计算1+2+…+50,
第二个线程计算51+52+…+100。
最后主线程相加子线程结果输出。
'''
total = 0
mutex = threading.Lock()  

def threadnum(start, end):
    for i in range(start, end+1):
        #print i
        global total
        mutex.acquire()
        total = total + i
        mutex.release()
        #print total

def main():
    print "请输入线程个数:"
    num = input()
    end = 100
    
    start_mid = 0
    end_mid = 0
    
    tid_arr = []
    for n in xrange(num):
        start_mid = end_mid + 1
        end_mid += end / num
        
        if n == num-1:
            end_mid = 100
        print start_mid, end_mid
        
        thd = threading.Thread(target=threadnum,args=(start_mid, end_mid))
        thd.start()
        tid_arr.append(thd)
    
    for tid in tid_arr:
        tid.join()
        
    print total, "all end, thanks"
    
if __name__ == "__main__":
    main()

推荐阅读更多精彩内容