Python 多线程

线程实现

python 的 thread 模块是比较底层的模块,threading 模块是对 thread 做了一些封装的,可以更好的使用

说明:python的threading.Thread类有一个run方法,用于定义线程的功能函数,可以在自己的线程类中覆盖该方法。而创建自己的线程实例后,通过Thread类的start方法,可以启动该线程,交给python虚拟机进行调度,当该线程获得执行的机会时,就会调用run方法执行线程

多线程执行

# coding=utf-8
import threading
import time


class HelloWorld(threading.Thread):
    def run(self):
        print(f"hello, world ~, my name is{self.name}")
        time.sleep(1)


if __name__ == '__main__':
    for i in range(5):
        hello_obj = HelloWorld()
        hello_obj.start()
View Code

可以看到同时打印了 hello, world ~,还有自己的 name(Thread-id);当调用 start() 时,才会真正的创建线程,并且开始执行

主线程会等待所有的子线程结束后才结束

# coding=utf-8
import threading
import time


class HelloWorld(threading.Thread):
    def __init__(self, num):
        threading.Thread.__init__(self)
        self.second = num

    def run(self):
        print(f"hello, world ~, my name is{self.name}")
        time.sleep(self.second)


if __name__ == '__main__':
    for i in range(5):
        hello_obj = HelloWorld(i)
        hello_obj.start()
    while True:
        # 查看当前运行的线程数量
        length = len(threading.enumerate())
        print(f"current running thread num is:{length}")
        if length <= 3:
            break
        time.sleep(1)
View Code

总结:

  1. 每个线程默认有一个名字,尽管上面的例子中没有指定线程对象的name,但是python会自动为线程指定一个名字
  2. 当线程的run()方法结束时该线程完成
  3. 无法控制线程调度顺序,但可以通过别的方式来影响线程调度的方式

 

多线程-共享全局变量

在一个进程内的所有线程共享全局变量,很方便在多个线程间共享数据

缺点就是,线程是对全局变量随意遂改可能造成多线程之间对全局变量的混乱(即线程非安全)

from threading import Thread
import time

g_num = 100


class Work1(Thread):
    def run(self):
        global g_num
        for i in range(3):
            g_num += 1

        print(f"----in work1, g_num is {g_num}---")
        

class Work2(Thread):
    def run(self):
        global g_num
        print(f"----in work2, g_num is {g_num}---")


print(f"---线程创建之前g_num is {g_num}---")

t1 = Work1()
t1.start()

# 延时一会,保证t1线程中的事情做完
time.sleep(1)

t2 = Work2()
t2.start()
View Code

多线程开发可能遇到的问题

假设两个线程 t1 和 t2 都要对全局变量 g_num (默认是0)进行加1运算,t1 和 t2 都各对 g_num 加10次,g_num 的最终的结果应该为 20

但是由于是多线程同时操作,有可能出现下面情况:

  1. 在 g_num=0 时,t1 取得 g_num=0。此时操作系统把 t1 调度为”sleeping”状态,把 t2 转换为”running”状态,t2 也获得 g_num=0
  2. 然后 t2 对得到的值进行加1并赋给 g_num,使得 g_num=1
  3. 然后操作系统又把 t2 调度为”sleeping”,把 t1 转为”running”,线程 t1 又把它之前得到的0加1后赋值给 g_num
  4. 这样导致虽然 t1 和 t2 都对 g_num 加1,但结果仍然是 g_num=1
    # coding=utf-8
    import time
    import threading
    from threading import Thread
    
    g_num = 0
    
    
    class Work1(Thread):
        def __init__(self, count):
            Thread.__init__(self)
            self.count = count
    
        def run(self):
            global g_num
            for i in range(self.count):
                g_num += 1
            # print(f"----in work1, g_num is {g_num}---")
    
    
    class Work2(Work1):
        pass
    
    
    print(f"---线程创建之前g_num is {g_num}---")
    
    count = 1000000
    
    t1 = Work1(count)
    t1.start()
    
    t2 = Work2(count)
    t2.start()
    
    while len(threading.enumerate()) != 1:
        time.sleep(1)
    
    print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)
    
    运行结果
    ---线程创建之前g_num is 0---
    2个线程对同一个全局变量操作之后的最终结果是:1275729
    View Code

 如果多个线程同时对同一个全局变量操作,会出现资源竞争问题,从而数据结果会不正确

   

 

posted @ 2019-05-09 20:58  kaichenkai  阅读(161)  评论(0编辑  收藏  举报