python——多线程

这篇博客探讨了Python中的多线程技术,包括如何使用threading模块创建线程,以及多线程中可能遇到的线程冲突问题。通过示例展示了函数和类两种方式创建线程,并强调了args参数的使用。为了解决线程冲突,文章提到了使用锁、wait事件、Semaphore限流和Barrier同步机制来实现线程的并发控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、多线程:
直接使用threading模块的Thread类来创建线程,多个线程可以共享进程的内存空间,Python的多线程并不能发挥CPU的多核特性。
二、创建多线程:

import threading
import win32api
第一种用函数创建多线程,但是需要处理让脚本主线程不死
第二种是基于类继承创建多线程
第三种:(不推荐使用)
threading.Thread(target=show,args=(i,)).start() # 切记这里的args是一个元组
threading.Thread(target=show,args=(i,)).start()

创建五个多线程求和(使用函数创建多线程),线程冲突,5个线程同时抢夺num的资源,导致最后结果错误

import _thread
NUM = 0
def A():
    global NUM
    for i in range(10000000):
        NUM += 1

    print(NUM)
    
for i in range(5):           # 这是子线程, 同时执行5次
    _thread.start_new_thread(A,())        # 前面是执行函数,后面是一个元组,可以不写前提是函数没有形参

while 1:       # 在这里加入死循环是为了脚本主线程不死,子线程才能运行
    pass
执行结果:
11781908
12025580
13214742
14260177
14316790

使用类创建多线程

NUM = 0
import threading
class WJL(threading.Thread):           # 继承threading.Thread类
    def __init__(self):
        threading.Thread.__init__(self)
        #self.NUM = 0

    def run(self):                    # 重写threading.Thread类中的run函数
        global NUM
        for _ in range(1000):
           NUM += 1
        print(NUM)

if __name__ == "__main__":

    for i in range(5):
        t=WJL()              # 初始化
        t.start()
    while 1:
        pass
执行结果:
1000
2000
3000
4000
5000

创建锁(必须得释放锁)可以解决线程冲突

import threading
import random
mutex = threading.Lock()          # 创建一个锁,threading.Lock()是一个类
NUM = 0

class Mythread(threading.Thread):
    def run(self):
        global NUM

        if mutex.acquire(1):  # 如果锁成功,那么线程继续干活,如果锁失败,下面的线程一直等待锁成功,1,代表独占
            for i in range(100):
                NUM += 1
            mutex.release()          # 释放锁
        print(NUM)

mythread =[]
for i in range(3):
    t = Mythread()
    t.start()
    mythread.append(t)

执行结果:
100
200
300
game over

类线程的乱序风格,会输出五个白框

import threading
import win32api


class Mythread(threading.Thread):  # 继承threading.Thread类
    def __init__(self, num):
        threading.Thread.__init__(self)  # 父类初始化
        self.num = num

    def run(self):  # 定义函数
        win32api.MessageBox(0, "王璐~~~" + str(self.num), 'wjl', 0)
        print(self.getName())  # 获取线程名


Mythd = []
for i in range(5):
    t = Mythread(i)  # 初始化
    print(i)
    t.start()  # 开启
    Mythd.append(t)  # 将乱序线程(同时抢夺run这个函数)加入列表

for j in Mythd:
    # 这里与顺序不同,上面显示所有的线程都加入Mthd列表(所以一次性跳出5个窗口,但是主线程还没死,因为有join卡住)。
    # j是线程
    j.join()  # 这里主线程同时等待所有线程都执行完毕,才执行“game over”
print("game over")
执行结果:
0
1
2
3
4
Thread-4
Thread-1
Thread-2
Thread-3
Thread-5
game over

多线程的通信,使用wait 等待事件,等待set消息

import threading
import time


def goevent():
    e = threading.Event()  # 事件

    def go():
        e.wait()  # 等待事件,线程卡顿,等待set消息
        print("go")

    threading.Thread(target=go).start() # 需要创建一个线程
    return e

t = goevent()
执行结果:go

使用threading.Semaphore(2)控制最大线程数,当超过限制数的时候就不执行,即最多限制数个线程可同时执行

import threading

import time

sem = threading.Semaphore(2)  # 限制最大线程数为2个
def gothread():
    with sem:  # 锁定数量
        for i in range(10):
            print(threading.current_thread().name, i)  # 打印线程名字
            time.sleep(1)


for i in range(5):
    threading.Thread(target=gothread).start()  # 乱序执行多线程,就可以考虑为有些cpu牛逼些能够执行快一点
执行结果:
Thread-1 0
Thread-2 0
Thread-2 1
Thread-1 1
Thread-1 2
Thread-2 2
Thread-1 3
Thread-2 3
Thread-1 4
Thread-2 4
Thread-1 5
Thread-2 5

使用threading.Barrier(2)控制线程数量a,即只有数量达到a才可以执行多线程,否则一直在等待

import threading
# 凑出线程数量,也就是说一定要至少凑成两个才能执行
# 换而言之,也就是说只有创建线程数是2,或者2的倍数才能全部执行
bar = threading.Barrier(2)

def sever():

    print(threading.current_thread().name,"start")
    bar.wait()
    print(threading.current_thread().name,"end")

for i in range(3):
    threading.Thread(target=sever).start()
执行结果:
Thread-1 start
Thread-2 start
Thread-2 end
Thread-1 end
Thread-3 start

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值