Pyhon线程

多线程注意点

  • 如果创建Thread时执行的函数运行结束,意味着该子线程结束。
  • 主线程结束,程序结束,主线程会等待子线程结束。
  • 子线程的开始是从调用start开始的。
  • 线程创建之后谁先执行是不确定的,可以通过添加sleep来指定顺序。
  • 查看线程个数使用len(threading.enumerate())
import threading
import time

def test1():
    for i in range(5):
        print("....test1....%d"%i)
        time.sleep(1)

def test2():
    for i in range(8):
        print("....test2....%d"%i)
        time.sleep(1)

def main():
    t1 = threading.Thread(target=test1)
    t2 = threading.Thread(target=test2)

    t1.start()
    t2.start()

    while True:
        print(threading.enumerate())
        if (len(threading.enumerate())<=1):
            break        
        time.sleep(1)
if __name__ == "__main__":
    main()

 共享全局变量

  • 共享全局变量可以方便多个线程共享数据
  • args传入一个元组作为参数
  • 不可变类型需要global声明,可变类型不需要
import threading
import time

# 定义一个全局变量
g_num = 100

def test1(temp):
    temp.append(33)
    print("in test1 g_num=%s" % str(temp))

def test2(temp):
    print("in test2 g_num=%s" % str(temp))

g_nums = [11, 22]

def main():
    # target指定将来哪个线程去哪个函数执行代码
    # args指定将来调用函数的参数
    t1 = threading.Thread(target=test1, args=(g_nums,))
    t2 = threading.Thread(target=test2, args=(g_nums,))

    t1.start()
    time.sleep(1)

    t2.start()
    time.sleep(1)

    print("in main g_num=%s" % str(g_nums))

if __name__ == "__main__":
    main()

共享全局变量造成资源竞争

  • 不同线程都要修改某个变量,比如都要执行g_num+=1,这个过程分为三步:
    1. 获得g_num的值
    2. 给这个值加一
    3. 把加一后的值赋给g_num
  • 如果第一个线程执行了前两步,获得g_num=0,然后加一,但还没有赋值给n_num就进入休眠,轮到第二个线程执行,获得的g_num的值还是0,加一后得到1,还没执行第三步,又轮到第一个线程,这时线程1会接着上次的操作,直接从第三步开始,得到g_num=1;再次轮到第二个线程,也接着从第三步开始,得到g_num=1,两个线程结束后本该得到g_num=2,这里确得到1.
  • 为了解决上述问题,引入互斥锁的概念,使用threading模块中的Lock,给可能冲突的代码段上锁、解锁。从而避免资源竞争引发的错误。
  • 当存在多个锁时,可能存在死锁问题,两个线程都等待对方解锁,程序设计中要尽量避免死锁。
import threading
import time

# 定义一个全局变量
g_num = 0

def test1(num):
    global g_num
    for i in range(num):
        mutex.acquire()
        g_num += 1
        mutex.release()
    print("in test1 g_num=%d" % g_num)

def test2(num):
    global g_num
    for i in range(num):
        mutex.acquire()
        g_num += 1
        mutex.release()
    print("in test2 g_num=%d" % g_num)


mutex = threading.Lock()
def main():
    # target指定将来哪个线程去哪个函数执行代码
    # args指定将来调用函数的参数
    t1 = threading.Thread(target=test1, args=(1000000,))
    t2 = threading.Thread(target=test2, args=(1000000,))

    t1.start()
    t2.start()

    while len(threading.enumerate()) != 1:
        time.sleep(1)

    print("in main g_num=%d" % g_num)

if __name__ == "__main__":
    main()

 

posted @ 2019-06-19 20:46  小飞的学习笔记  阅读(167)  评论(0编辑  收藏  举报