0

0

Python多线程中线程间资源共享和常用的锁机制的介绍

不言

不言

发布时间:2018-10-26 17:18:59

|

3242人浏览过

|

来源于CSDN

转载

本篇文章给大家带来的内容是关于Python多线程中线程间资源共享和常用的锁机制的介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

本文将简单介绍多线程编程中的线程间资源共享和常用的锁机制。

在多线程编程中,常常会涉及到线程间的资源共享, 常用资源共享常用方式:

  • 全局变量(global)

  • queue(from queue import Queue)

常用的资源共享锁机制:

立即学习Python免费学习笔记(深入)”;

  • Lock

  • RLock

  • Semphore

  • Condition

(一) 线程间资源共享

  1. 使用全局变量可以实现线程间的资源共享,关键字global

代码演示:

from threading import Thread, Lock
lock = Lock()
total = 0

'''如果不使用lock那么,最后得到的数字不一定为0;同时loack不支持连续多次acquire,如果这样做了的后果是死锁!'''
def add():
    global total
    global lock
    for i in range(1000000):
        lock.acquire()
        total += 1
        lock.release()
    
def sub():
    global total
    global lock
    for i in range(1000000):
        lock.acquire()
        total -= 1
        lock.release()
    
thread1 = Thread(target=add)
thread2 = Thread(target=sub)


# 将Thread1和2设置为守护线程,主线程完成时,子线程也一起结束
# thread1.setDaemon(True)
# thread1.setDaemon(True)

# 启动线程
thread1.start()
thread2.start()

# 阻塞,等待线程1和2完成,如果不使用join,那么主线程完成后,子线程也会自动关闭。
thread1.join()
thread2.join()

total
  1. 使用queue共享资源,queue是线程安全的。

from threading import Thread, Lock
from queue import Queue

def add(q):
    if q.not_full:
        q.put(1)
    
def sub(q):
    if q.not_empty:
        recv = q.get()
        print(recv)
        q.task_done()
        
if __name__ =='__main__':
    # 设置q最多接收3个任务,Queue是线程安全的,所以不需要Lock
    qu = Queue(3)
    thread1 = Thread(target=add, args=(qu,))
    thread2 = Thread(target=sub, args=(qu,))
    thread1.start()
    thread2.start()
    # q队列堵塞,等待所有任务都被处理完。
    qu.join()

(二) 锁(Lock/RLock/Condition/Semphore)

  1. Lock

Lock 不能连续acquire锁,不然会死锁,Lock 资源竞争可能会导致死锁。

Lock 会降低性能。

蚂蚁PPT
蚂蚁PPT

AI在线智能生成PPT

下载
from threading import Thread, Lock
lock = Lock()
total = 0

'''如果不使用lock那么,最后得到的数字不一定为0;同时lock不支持连续多次acquire,如果这样做了的后果是死锁!'''
def add():
    global total
    global lock
    for i in range(1000000):
        lock.acquire()
        total += 1
        lock.release()
    
def sub():
    global total
    global lock
    for i in range(1000000):
        lock.acquire()
        total -= 1
        lock.release()
    
thread1 = Thread(target=add)
thread2 = Thread(target=sub)

# 将Thread1和2设置为守护线程,主线程完成时,子线程也一起结束
# thread1.setDaemon(True)
# thread1.setDaemon(True)

# 启动线程
thread1.start()
thread2.start()

# 阻塞,等待线程1和2完成,如果不使用join,那么主线程完成后,子线程也会自动关闭。
thread1.join()
thread2.join()
total
  1. RLock

RLock 可以连续acquire锁,但是需要相应数量的release释放锁

因可以连续获取锁,所以实现了函数内部调用带锁的函数

from threading import Thread, Lock, RLock
lock = RLock()
total = 0
def add():
    global lock
    global total
    # RLock实现连续获取锁,但是需要相应数量的release来释放资源
    for i in range(1000000):
        lock.acquire()
        lock.acquire()
        total += 1
        lock.release()
        lock.release()
def sub():
    global lock
    global total
    for i in range(1000000):
        lock.acquire()
        total -= 1
        lock.release()
thread1 = Thread(target=add)
thread2 = Thread(target=sub)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
total
  1. Condition 条件变量

Condition条件变量服从上下文管理协议:使用with语句获取封闭块持续时间的关联锁。

wait()方法释放锁,然后阻塞,直到另一个线程通过调用notify()或notify_all()唤醒它。一旦被唤醒,wait()重新获得锁并返回。也可以指定超时。

先启动wait接收信号的函数,处于阻塞等待状态,再启动notify的函数发出信号

from threading import Thread, Condition
'''聊天
    Peaple1 : How are you?
    Peaple2 : I`m fine, thank you!
    
    Peaple1 : What`s your job?
    Peaple2 : My job is teacher.
    
'''

def Peaple1(condition):
    with condition:
        print('Peaple1 : ', 'How are you?')
        condition.notify()
        condition.wait()
        
        print('Peaple1 : ', 'What`s your job?')
        condition.notify()
        condition.wait()

def Peaple2(condition):
    with condition:
        condition.wait()
        print('Peaple2 : ', 'I`m fine, thank you!')
        condition.notify()
        
        condition.wait()
        print('Peaple2 : ', 'My job is teacher.')
        condition.notify()


if __name__ == '__main__':
    cond = Condition()
    thread1 = Thread(target=Peaple1, args=(cond,))
    thread2 = Thread(target=Peaple2, args=(cond,))
    
    # 此处thread2要比thread1提前启动,因为notify必须要有wait接收;如果先启动thread1,没有wait接收notify信号,那么将会死锁。
    thread2.start()
    thread1.start()

#     thread1.join()
#     thread2.join()
  1. Semphore

该类实现信号量对象。信号量管理一个原子计数器,表示release()调用的数量减去acquire()调用的数量加上一个初始值。如果需要,acquire()方法会阻塞,直到它可以返回而不使计数器为负。如果没有给出,则值默认为1。

#Semaphore 是用于控制进入数量的锁
#文件, 读、写, 写一般只是用于一个线程写,读可以允许有多个

import threading
import time

class HtmlSpider(threading.Thread):
    def __init__(self, url, sem):
        super().__init__()
        self.url = url
        self.sem = sem

    def run(self):
        time.sleep(2)
        print("Download {html} success\n".format(html=self.url))
        self.sem.release()

class UrlProducer(threading.Thread):
    def __init__(self, sem):
        super().__init__()
        self.sem = sem

    def run(self):
        for i in range(20):
            self.sem.acquire()
            html_thread = HtmlSpider("https://www.baidu.com/{}".format(i), self.sem)
            html_thread.start()

if __name__ == "__main__":
    # 控制锁的数量, 每次同时会有3个线程获得锁,然后输出
    sem = threading.Semaphore(3)
    url_producer = UrlProducer(sem)
    url_producer.start()

(三)简单介绍多进程编程

  1. 多进程编程中进程间不能实现全局变量共享,也不能使用queue.Queue

  2. 多进程编程通信需要使用Queue,Pipe

  3. 如果使用进程池进程编程需要使用Manger的实例的queue来实现通信

相关文章

python速学教程(入门到精通)
python速学教程(入门到精通)

python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
C++ 高级模板编程与元编程
C++ 高级模板编程与元编程

本专题深入讲解 C++ 中的高级模板编程与元编程技术,涵盖模板特化、SFINAE、模板递归、类型萃取、编译时常量与计算、C++17 的折叠表达式与变长模板参数等。通过多个实际示例,帮助开发者掌握 如何利用 C++ 模板机制编写高效、可扩展的通用代码,并提升代码的灵活性与性能。

10

2026.01.23

php远程文件教程合集
php远程文件教程合集

本专题整合了php远程文件相关教程,阅读专题下面的文章了解更多详细内容。

29

2026.01.22

PHP后端开发相关内容汇总
PHP后端开发相关内容汇总

本专题整合了PHP后端开发相关内容,阅读专题下面的文章了解更多详细内容。

21

2026.01.22

php会话教程合集
php会话教程合集

本专题整合了php会话教程相关合集,阅读专题下面的文章了解更多详细内容。

21

2026.01.22

宝塔PHP8.4相关教程汇总
宝塔PHP8.4相关教程汇总

本专题整合了宝塔PHP8.4相关教程,阅读专题下面的文章了解更多详细内容。

13

2026.01.22

PHP特殊符号教程合集
PHP特殊符号教程合集

本专题整合了PHP特殊符号相关处理方法,阅读专题下面的文章了解更多详细内容。

11

2026.01.22

PHP探针相关教程合集
PHP探针相关教程合集

本专题整合了PHP探针相关教程,阅读专题下面的文章了解更多详细内容。

8

2026.01.22

菜鸟裹裹入口以及教程汇总
菜鸟裹裹入口以及教程汇总

本专题整合了菜鸟裹裹入口地址及教程分享,阅读专题下面的文章了解更多详细内容。

55

2026.01.22

Golang 性能分析与pprof调优实战
Golang 性能分析与pprof调优实战

本专题系统讲解 Golang 应用的性能分析与调优方法,重点覆盖 pprof 的使用方式,包括 CPU、内存、阻塞与 goroutine 分析,火焰图解读,常见性能瓶颈定位思路,以及在真实项目中进行针对性优化的实践技巧。通过案例讲解,帮助开发者掌握 用数据驱动的方式持续提升 Go 程序性能与稳定性。

9

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 16.5万人学习

Django 教程
Django 教程

共28课时 | 3.4万人学习

Excel 教程
Excel 教程

共162课时 | 13.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号