、python多任务编程----多线程

多线程编程:

    线程:每一个进程都会有一个主线程,先有进程,后有线程。线程是CPU调度的基本单位。

    主进程 > 子进程 > 主线程 > 子线程 > 主协程 > 子协程

     代码结构和进程一般无二。


代码示例:

import threading

import time

def dance():

    for i in range(5):

        print(f"跳舞{i}", threading.current_thread())

        time.sleep(1)

def sing():

    for i in range(5):

        print(f"唱歌{i}")

        time.sleep(1)

if __name__ == "__main__":

    print("这是主线程")

    dance_thr = threading.Thread(target=dance, name="my_dance")

    sing_thr = threading.Thread(target=sing, name="my_sing")

    dance_thr.start()

    sing_thr.start()

    dance_thr.join()

    sing_thr.join()

    print("主线程结束")


线程注意事项:

    1. 线程执行时无序的

    2. 线程之间共享全局变量

    3. 线程之间共享全局变量存在资源竞争,当数据量特别大(1000000)的时候,会令数据错乱。 解决方法:线程.join(), 互斥锁。

    4. 设置线程守护主线程:如果有多个线程或进程,要每个都守护。

           4.1 线程.setDaemon()

           4.2 线程.deamon = True

           4.3 work2_thr = threading.Thread(target=work2, daemon=True)


关于资源竞争问题:

示例代码:

# 读者运行后,会发现每次结果都不一样。是因为他们都去抢num这个全局变量,所以最终导致数据错乱

import threading

num = 0

def work1():

    global num

    for i in range(1000000):

        num += i

    print(num)

def work2():

    global num

    for i in range(1000000):

        num += i

    print(num)

if __name__ == '__main__':

    work1_thr = threading.Thread(target=work1)

    work2_thr = threading.Thread(target=work2)

    work1_thr.start()

    work2_thr.start()

以上问题有两种解决方案:互斥锁,调用子线程.join()方法


(1)调用join()方法:代码如下

if __name__ == '__main__':

    work1_thr = threading.Thread(target=work1)

    work2_thr = threading.Thread(target=work2)

    work1_thr.start()

    work1_thr.join()  # 调用子线程.join()方法

    work2_thr.start()


(2)互斥锁方法解决资源竞争问题

互斥锁作用:保证同一时间段只有一个线程在操作全局变量

    1.创建锁

    lock = threaing.Lock()

    2.上锁

    lock.acquire()  # 用在使用全局变量前

    代码

    3.释放锁

    lock.release()

4. 设置线程守护主线程

  方法一:

  if __name__ == '__main__':

    work1_thr = threading.Thread(target=work1)

    work2_thr = threading.Thread(target=work2)

    work1_thr.daemon = True

    work2_thr.daemon = True

    work1_thr.start()

    work2_thr.start()

    print("主线程结束")

方法二:

    if __name__ == '__main__':

    work1_thr = threading.Thread(target=work1)

    work2_thr = threading.Thread(target=work2)

    work1_thr.setDaemon(True)

    work2_thr.setDaemon(True)

    work1_thr.start()

    work2_thr.start()

    print("主线程结束")

方法三:

    if __name__ == '__main__':

    work1_thr = threading.Thread(target=work1, daemon=True)

    work2_thr = threading.Thread(target=work2, daemon=True)

    work1_thr.start()

    work2_thr.start()

    print("主线程结束")


线程和进程的对比:

关系对比:

1.先有进程,后有线程

2.一个进程肯定有一个对比,也可以创建多个线程

区别对比:

1.进程之间不共享全局变量

2.线程之间共享全局变量,出现资源竞争问题,采用互锁锁或线程同步

3.创建进程的资源开销要比创建线程大

4.进程是操作系统资源分配的基本单位,线程是CPU分配资源的基本单位

5.线程不能够独立运行,必须依存在进程中

6.多进程开发比单进程多线程开发稳定性要强

优缺点对比:

进程优缺点:

    优点:可以使用多核。

    缺点:资源开销大

线程优缺点:

    优点:资源开销小

    缺点:不能使用多核

GIL(全局解释器锁):把多线程锁住了,使得多线程没办法使用多核。

你可能感兴趣的:(、python多任务编程----多线程)