python线程详解

线程条件,模块threading

启动方式

 for i in range(2):
        t = threading.Thread(target=fib, args=(35,),kwargs=None,daemon=None,name=None)
        t.start()  #开始运行

#参数介绍        
target:目标函数名称
args: 传递元组参数
kwargs:传递关键字参数
daemon:是否为守护进程 默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置
name:是指的进程名称

#线程对象方法
t.start()  #开始运行
t.join()    默认:子进程和父进程是异步执行的。所以保证子进程执行完需要加
t.isAlive() 返回true/false, 线程是否存活
t.isDaemon() 返回true/false, 线程是否为守护进程

线程变量

线程共享全局变量,用global修改即可

import threading
share_var = 3

def share(var):
    global share_var
    share_var = var + 1
    print('--------var', share_var, id(share_var))
    return share_var


if __name__ == '__main__':
    thread_list = []
    m = Manager()
    share_dict = m.dict()
    for i in range(2):
        m = threading.Thread(target=share, args=(share_var,)) #1
        thread_list.append(m)
        m.start()
    for i in thread_list:
        i.join()
#Thread
# --------var 4 140726610685792
# --------var 5 140726610685824
# ------------end 5

常用方法

threading.current_thread()

返回当前线程对象

threading.enumerate()

返回当前存在的所有线程对象的列表

threading.get_ident()

返回线程pid

threading.main_thread()

返回主线程对象,类似 threading.current_thread();只不过一个是返回当前线程对象,一个是返回主线程对象

@profile
def hasthread():
    for i in range(2):
        t = threading.Thread(target=fib, args=(35,))
        t.start()
    main_thread = threading.current_thread() #返回当前Thread对象,对应于调用者的控制线程.
    print(main_thread)
    print('---------', threading.enumerate()) #返回当前活动的所有Thread对象的列表。这个列表包括守护线程,由守护线程创建的虚拟线程对象
    for t in threading.enumerate():
        if t is main_thread:
            continue
        t.join()

#用于线程同步机制的方法

threading.Lock()
from threading import Lock

lock = Lock()
class Account:
    def __init__(self, balance):
        self.balance = balance

def draw(account, amount):
    with lock:
        time.sleep(0.1)
        if account.balance >= amount:
            print(threading.current_thread().name,"取钱成功")
            account.balance -= amount
            print(threading.current_thread().name,"余额", account.balance)

        else:
            print(threading.current_thread().name, "取钱失败,余额不足")

if __name__ == '__main__':
    account = Account(1000)
    ta = threading.Thread(name="ta", target=draw,args=(account, 800))
    tb = threading.Thread(name="tb", target=draw,args=(account, 800))
    ta.start()
    tb.start()

#线程互斥锁

threading.Rlock()

#线程可重入锁. 互斥锁acquire后无release,下次acquire则一直阻塞。重入锁可以多次acquire,引用计数-1.

threading.Condition()
import threading
import time

product = 19
# 一个线程等待特定条件,而另一个线程发出特定条件满足的信号。最好说明的例子就是「生产者 / 消费者」模型:

def consumer(cond):
    global product
    t = threading.current_thread()
    with cond:
        cond.wait()  #等待被唤醒

        if product > 0:
            product -= 1
            print(f"{t.name}: resource ready")
        else:
            print("resource exhausted")


def producer(cond):
    global product
    t = threading.current_thread()
    with cond:
        print(f"{t.name}: Making resource available")
        product += 1
        cond.notifyAll()  # 释放waiter锁,唤醒消费者


condition = threading.Condition()
c1 = threading.Thread(name="c1", target=consumer, args=(condition,))
c2 = threading.Thread(name="c2", target=consumer, args=(condition,))
p1 = threading.Thread(name="p1", target=producer, args=(condition,))
p2 = threading.Thread(name="p2", target=producer, args=(condition,))

c1.start()
time.sleep(1)
c2.start()
time.sleep(1)
p1.start()
p2.start()

线程条件锁,和上面一样提供了acquire, release方法。

threading.Semaphore()

线程信号量:对共同资源访问的对象数量。互斥锁等同时间段只允许一个对象访问,信号量这里可以指定对象数量。

import time
import threading
from random import random
from threading import Thread,Semaphore

def foo(tid, sema):
    with sema:
        wt = random() * 2
        time.sleep(wt)
    print(f"{tid} release sema")

def foo1(tid):
    wt = random() * 2
    time.sleep(wt)
    print(f"{tid} release sema")

if __name__ == '__main__':
    tic = time.time()
    sema = Semaphore(10)  #信号量指的是对共同资源访问的对象数量
    threads = []
    for i  in range(100):
        t = Thread(target=foo, args=(i,sema))
        threads.append(t)
        t.start()
    for t in threads:
        t.join()

    toc = time.time()
    print(f"10个结束时间:{toc-tic}")
threading.Event()

使用场景:python线程的事件用于主线程控制其他线程的执行
事件其实就相当于一个全局变量(设置为True,未设置为False),线程通过这个全局变量的状态来控制自身
enent可以通过设置、等待、清除一个标识(flag),来进行线程间的控制

event只要set,clear,wait三个方法
使用前先实例化event = threading.Event()
event.wait()#线程阻塞,等待标志位被设置.flag=False,程序执行event.wait会阻塞。为True不阻塞
event.wait(second) 不写second就一直等待
event.set()#设置标志位为True
event.clear()#清除标志位,设置为False
enent.isSet()#标志位是否被设置

import time
import threading
from random import randint

TIMEOUT = 2

def consumer(event, l):
    t = threading.currentThread()
    while 1:
        event_is_set = event.wait(TIMEOUT)
        if event_is_set:
            try:
                integer = l.pop()
                print('{} popped from list by {}'.format(integer, t.name))
                event.clear()  # 重置事件状态
            except IndexError:  # 为了让刚启动时容错
                pass


def producer(event, l):
    t = threading.currentThread()
    while 1:
        integer = randint(10, 100)
        l.append(integer)
        print('{} appended to list by {}'.format(integer, t.name))
        event.set()  # 设置事件
        time.sleep(1)


event = threading.Event()
l = []
threads = []
for name in ('consumer1', 'consumer2'):
    t = threading.Thread(name=name, target=consumer, args=(event, l))
    t.start()
    threads.append(t)

p = threading.Thread(name='producer1', target=producer, args=(event, l))
p.start()
threads.append(p)

for t in threads:
    t.join()

参考连接:
lr:
1)https://blog.csdn.net/jgw2008/article/details/84759696

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python多线程是指在Python程序中同时执行多个线程的编程技术。使用多线程编程具有以下几个优点:首先,线程之间可以共享内存,这使得数据共享和通信更加容易。其次,创建线程的代价比创建进程小得多,因此使用多线程来实现多任务并发执行比使用多进程更高效。此外,Python语言内置了多线程功能支持,简化了多线程编程的复杂性\[1\]。 然而,需要注意的是,在Python 2.x版本中,存在全局解释器锁(GIL),它限制了同一进程中只能有一个线程执行Python字节码。这意味着在多核CPU上,Python多线程并不能充分利用多核处理器的优势,因为只有拿到GIL锁的线程才能执行\[2\]。 尽管如此,多线程在IO密集型代码中仍然能够提升效率。在涉及文件处理、网络爬虫等需要进行IO操作的任务中,多线程可以避免不必要的IO等待时间,提高程序的执行效率。因此,对于IO密集型代码,Python多线程是比较友好的\[3\]。 总结起来,Python多线程编程具有一些优点,但也存在一些限制。在选择是否使用多线程时,需要根据具体的应用场景和需求来进行权衡和选择。 #### 引用[.reference_title] - *1* [python多线程详解(超详细)](https://blog.csdn.net/m0_67900727/article/details/123399522)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [python多线程详解](https://blog.csdn.net/weixin_39612023/article/details/109945251)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云中烤飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值