python threading模块

本文介绍了Python3中使用threading模块进行多线程编程的基础操作,如获取线程数、查看线程信息以及join方法的使用。由于GIL的存在,Python的多线程无法实现真正的并发,但在IO密集型任务中仍能提升效率。文章通过代码示例探讨了join方法的使用场景以及Lock的重要性,并展示了在没有锁的情况下,线程执行的不确定性及其与GIL的关系。
摘要由CSDN通过智能技术生成
概述

python3中建议用threading,原先的thread重命名为_thread。在python中多线程并没有那么有效,因为GIL的存在所以线程也没法做到真正的并发,但对于IO比较频繁的程序,多线程还是能很好的起作用的。

补充:背的时候觉得自己总能记住但是过几个星期又忘了…
并发: 宏观角度同时而微观顺序。
并行:微观同时。

一些基本操作
获取已激活的线程数
threading.active_count()
# 2
查看所有线程信息
threading.enumerate()
查看现在正在运行的线程
threading.current_thread()
添加线程
def thread_job():
    print('This is a thread of %s' % threading.current_thread())

def main():
    thread = threading.Thread(target=thread_job)   # 定义线程,常用参数还有args和name,分别是传给target的参数和给这个线程取得名字
    thread.start()  # 让线程开始工作
    thread.join()  # 不加join则程序会往下走,尽管线程还没运行完
    
if __name__ == '__main__':
    main()
关于join

被调用 join() 方法的线程会一直阻塞调用者的线程,直到自己结束。
当你想要线程A B都结束之后主函数才运行,比如print(“done”)时,你可以选择join。
而当你想让线程和主线程同时运行的时候不要加入join。比如当你把playsound加入线程并join后,主线程会暂停,直到音乐播完,所以这种情况我们不应该join()
join与否是关键,若处理不好则会变得和单线程没有区别。

Lock
thread_lock = threading.Lock()  # 实例一个lock
代码分析(失败)

这段代码还有些许疑问

  • 为什么C阻塞的时候线程A B不会获得CPU呢?
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : therading_test.py
# @Author: wfxt
# @Date  : 2019/11/28
# @Desc  :

import threading
import time

outside_x = 0
outside_y = 0


class MyThread(threading.Thread):  # 继承threading模块中的Thread类(类的首字母大写)
    def __init__(self, name, x, y, rest_time):
        threading.Thread.__init__(self)  # 继承Thread的构造函数
        self.name = name
        self.x = x
        self.y = y
        self.rest_time = rest_time
    
    def update_x(self, x):
        print("开始线程: " + self.name)
        # thread_lock_x.acquire()
        self.x = x
        global outside_x
        print(self.name, "休息", str(self.rest_time), "s...")
        time.sleep(self.rest_time)
        outside_x = self.x
        # thread_lock_x.release()
        print("outside x,y:", outside_x, outside_y)
        print(self.name + " 结束")
    
    def update_y(self, y):
        print("开始线程: " + self.name)
        # thread_lock_y.acquire()
        self.y = y
        global outside_y
        print(self.name, "休息", str(self.rest_time), "s...")
        time.sleep(self.rest_time)
        outside_y = self.y
        # thread_lock_y.release()
        print("outside x,y:", outside_x, outside_y)
        print(self.name + " 结束")
    

def sum_outside_xy():
    sum_xy = outside_x + outside_y
    print("outside x,y:", outside_x, outside_y)
    print("sum:", sum_xy)


thread_lock_x = threading.Lock()
thread_lock_y = threading.Lock()
threads = []


def main():
    threadA = MyThread("Thread-A", 1, 2, 0.5)
    threadB = MyThread("Thread-B", 4, 5, 1)
    threadC = MyThread("Thread-C", 7, 8, 5)
    threads.append(threadA)
    threads.append(threadB)
    threads.append(threadC)
    for thread in threads:
        thread.start()
        thread.deamon = True
        # thread.join()
    threadC.update_x(77)
    threadA.update_x(11)
    threadB.update_y(88)
    sum_outside_xy()


if __name__ == '__main__':
    main()

写这段代码的时候要吐了,运行结果如下(加不加锁运行都一样),C在暂停了5s后才开始的A,这就是python的GIL作怪了

Thread-C 休息 5 s...
outside x,y: 77 0
Thread-C 结束
开始线程: Thread-A
Thread-A 休息 0.5 s...
outside x,y: 11 0
Thread-A 结束
开始线程: Thread-B
Thread-B 休息 1 s...
outside x,y: 11 88
Thread-B 结束
outside x,y: 11 88
sum: 99
代码分析
global_n = 0

def job1():
    global global_n
    for i in range(10):
        global_n += 1
        print('job1', global_n)


def job2():
    global global_n
    for i in range(10):
        global_n += 10
        print('job2', global_n)

    t1 = threading.Thread(target=job1)
    t2 = threading.Thread(target=job2)
    t1.start()
    t2.start()
    # t1.join()  # 这里join与否都可能会乱序
    # t2.join()

有时候乱序,有时候正常

job1 1
job1 2
job1job2 3
 13job1
job2  14
job1 24
job225
job1  3536
job1 
job2 4737
job1 48
job1 49
job1 50

job2 60
job2 70
job2 80
job2 90
job2 100
job2 110

当我们加入锁之后

thread_lock_n = threading.Lock()


def job1():
    global global_n
    thread_lock_n.acquire()
    for i in range(10):
        global_n += 1
        print('job1', global_n)
    thread_lock_n.release()


def job2():
    global global_n
    thread_lock_n.acquire()
    for i in range(10):
        global_n += 10
        print('job2', global_n)
    thread_lock_n.release()

显示永远是正常的

job1 1
job1 2
job1 3
job1 4
job1 5
job1 6
job1 7
job1 8
job1 9
job1 10
job2 20
job2 30
job2 40
job2 50
job2 60
job2 70
job2 80
job2 90
job2 100
job2 110
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值