Python 线程和锁
创始人
2025-05-28 18:44:34
0

线程的使用

        1. 导入包 import threading

        2.创建线程 thread1 =  threading.Thread(tag="函数名",args=(参数,))

        3.开启线程 thread1.start()

        tag传递的是函数名,而不是函数的调用,需要对函数传递参数使用args,其接收的元组类型,所以当只有一个参数需要传递时,需要加上(,),保证其是元组的类型

        thread.join()函数的是让主线程的子线程全部执行完再去执行主线程

import threadingdef add(lock):global totalfor i in range(1000):total += 1def desc(lock):global totalfor i in range(1000):total -= 1if __name__ == "__main__":lock = Lock()total = 0thread1 = threading.Thread(target=add)thread2 = threading.Thread(target=desc)thread1.start()thread2.start()thread1.join()thread2.join()print(total)

线程的中的锁

Lock锁的需要获取acquire锁后释放release锁才行,获取锁后,其他线程使用该锁都需要等待已获取该锁的线程释放后才能进入线程,一直等待锁的释放

lock = Lock()

lock.acqurie()后必须要lock.release(),

锁一定会影响性能

也有可能会造成死锁

“锁住”变量total

import threading
from threading import Lock,RLockdef add(lock):global totalfor i in range(1000):lock.acquire()total += 1lock.release()def desc(lock):global totalfor i in range(1000):lock.acquire()total -= 1lock.release()if __name__ == "__main__":lock = Lock()total = 0thread1 = threading.Thread(target=add,args=(lock,))thread2 = threading.Thread(target=desc,args=(lock,))thread1.start()thread2.start()print(total)

 RLock锁能够在一个线程内多次获取锁,但一定要保证acquire和release的次数要对应,

rlock = RLock()

rlock.acquire()

rlock.acquire()

rlock.release()

rlock.release()

例子:

import threading
from threading import RLockdef do_something(rlock):rlock.acquire()# dorlock.release()def add(lock):global totalfor i in range(1000):lock.acquire()do_something(lock)total += 1lock.release()if __name__ == "__main__":rlock = RLock()total = 0thread1 = threading.Thread(target=add,args=(rlock,))thread1.start()print(total)

控制线程的数量

        1. 导入包 import threading.Semaphore

        2.控制线程数量 sem = threading.Semaphore(最大的数量)

        3.开启锁 线程创建前添加锁 sem.acqurie()

        4.释放锁 线程完成后释放锁 sem.release()

        Semaphore是在设定的最大线程数后,每创建一个线程最大线程数就减一同时获得一个锁,当等于0时,就阻塞,等待锁的释放

import threading
import timeclass GetHtml(threading.Thread):def __init__(self,url,sem):super().__init__()self.sem = semself.url = urldef run(self):time.sleep(2)print(f'start to get html:{self.url}')self.sem.release()if __name__ == '__main__':sem = threading.Semaphore(5)for i in range(20):sem.acquire()get_html = GetHtml(url=f"url_{i}",sem=sem)get_html.start()

线程池用法

        线程池可以获取某一个线程的状态以及该线程的返回值

        1. 导入包 from concurrent.futures import ThreadPoolExecutor

        2. 创建线程池对象 executor = TreadPoolExecutor(最大数量)

        3. 提交线程任务 task1 = executor.submit(函数名,参数)

        获取线程的状态:task1.done()

        获取线程的返回值: task1.result()

        

        取消某一线程:task2.cancel()

        需要注意的是只有进入线程池的任务才能被取消,正在运行或已在线程的任务不能被取消

import time
from concurrent.futures import ThreadPoolExecutordef get_html(times):time.sleep(times)print(f"暂停{times}秒,执行成功")result = f"time is {times}"return resultif __name__ == '__main__':executor = ThreadPoolExecutor(2)task1 = executor.submit(get_html,3)task1.done()task1.result()

        

        进阶用法

        多个任务的完成,使用as_complete包或map方法,其都是返回一个生成器对象

        as_complete 方法是哪个线程完成先返回

        map方法是按照传递的线程返回

        

import time
from concurrent.futures import ThreadPoolExecutor
from concurrent.futures import as_completeddef get_html(times):time.sleep(times)print(f"暂停{times}秒,执行成功")result = f"time is {times}"return resultif __name__ == '__main__':executor = ThreadPoolExecutor(2)times_list = [2,4,3,1]start_time = time.time()all_tasks = [executor.submit(get_html, time) for time in times_list]for future in as_completed(all_tasks):print(future.done())data = future.result()print(f"第一种方法,按照线程完成的顺序返回{data}")end_time = time.time()print(f"总计用时:{end_time - start_time}")print("==============================================")# 第二种方法start_time = time.time()for data in executor.map(get_html,times_list):print(f"第二种方法,是对应传入的顺序所返回,返回:{data}")end_time = time.time()print(f"总计用时:{end_time - start_time}")

        

 

        

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...