python-- 锁Lock

简介: python-- 锁Lock

银行存取钱


银行存取钱是同时对一个数据操作,容易造成数据混乱,解决方法是加锁

from multiprocessing import Process
from time import sleep
def get_money(num):  # 取钱
    num -= 1
    print('子进程:', num)
if __name__ == '__main__':
    money_num = 100
    p = Process(target=get_money, args=(money_num,))
    p.start()
    p.join()  # 等子进程结束
    print(money_num)

结果:

子进程: 99
100

数据不共享原因导致的


共享内存


from multiprocessing import Process, Value
from time import sleep
def get_money(num):  # 取钱
    num.value -= 1
    print('子进程:', num.value)
if __name__ == '__main__':
    money_num = Value('i', 100)
    p = Process(target=get_money, args=(money_num,))
    p.start()
    p.join()
    print(money_num.value)

结果:

子进程: 99
99

要共享内存有多个方法,这里用Value,首先要导入,money_num=Value('i',100)这句话的Value接收两个参数,第一个是数据类型,第二个是这个类型的值,取值的时候要用x.value

银行取钱问题

from multiprocessing import Process, Value
from time import sleep
def get_money(num):  # 取钱
    for i in range(100):
        num.value -= 1
        sleep(0.01)
def put_money(num):  # 存取
    for i in range(100):
        num.value += 1
        sleep(0.01)
if __name__ == '__main__':
    money_num = Value('i', 100)
    p = Process(target=get_money, args=(money_num,))
    p.start()  # 取钱
    p1 = Process(target=put_money, args=(money_num,))
    p1.start()  # 存取
    p1.join()
    p.join()
    print(money_num.value)

多执行几次,有时候是100,有时候小于100,有时候大于100


锁 Lock


from multiprocessing import Process, Lock
l = Lock()  # 实例化
l.acquire()  # 加锁。拿走钥匙,锁门,不让其他人进屋
l.release()  # 释放锁。还钥匙,开门,允许其他人进屋

银行存取钱加锁

from multiprocessing import Process, Value, Lock
from time import sleep
def get_money(num, l):  # 取钱
    l.acquire()
    for i in range(100):
        num.value -= 1
        sleep(0.01)
    l.release()
def put_money(num, l):  # 存取
    for i in range(100):
        l.acquire()  # 建议小范围的加锁
        num.value += 1
        l.release()
        sleep(0.01)
if __name__ == '__main__':
    l = Lock()  # 实例化锁
    money_num = Value('i', 100)
    p = Process(target=get_money, args=(money_num, l))
    p.start()  # 取钱
    p1 = Process(target=put_money, args=(money_num, l))
    p1.start()  # 存取
    p1.join()
    p.join()
    print(money_num.value)

不管操作多少次都是100

遇见l.acquire()给数据加个锁,别的进程就不能操作这个数据了,直到l.release()之后其他的进程才可以操作锁,建议小范围内加锁


模拟 12306 强票


from multiprocessing import Process, Lock
import time
def check(i):
    with open('余票') as f:
        con = f.read()
    print('第%s个人查到余票还剩%s张' % (i, con))
def buy_ticket(i, l):
    l.acquire()  # 拿钥匙,锁门
    with open('余票') as f:
        con = int(f.read())
        time.sleep(0.1)
    if con > 0:
        print('\033[31m 第%s个人买到票了\033[0m' % i)
        con -= 1
    else:
        print('\033[32m 第%s个人没有买到票\033[0m' % i)
    time.sleep(0.1)  # 是指 买完票后,把余票数量重写写入数据库的时间延迟
    with open('余票', 'w') as f:
        f.write(str(con))
    l.release()  # 还钥匙,开门
if __name__ == '__main__':
    l = Lock()
    for i in range(10):
        p_ch = Process(target=check, args=(i + 1,))
        p_ch.start()
    for i in range(10):
        p_buy = Process(target=buy_ticket, args=(i + 1, l))
        p_buy.start()

新建一个 “余票” 的文件,写个12

执行结果

第1个人查到余票还剩12张
第2个人查到余票还剩12张
第3个人查到余票还剩12张
第4个人查到余票还剩12张
第5个人查到余票还剩12张
第6个人查到余票还剩12张
第7个人查到余票还剩12张
第8个人查到余票还剩12张
第9个人查到余票还剩12张
第10个人查到余票还剩12张
 第1个人买到票了
 第2个人买到票了
 第3个人买到票了
 第4个人买到票了
 第5个人买到票了
 第6个人买到票了
 第7个人买到票了
 第8个人买到票了
 第9个人买到票了
 第10个人买到票了

相关文章
|
5月前
|
分布式计算 并行计算 安全
在Python Web开发中,Python的全局解释器锁(Global Interpreter Lock,简称GIL)是一个核心概念,它直接影响了Python程序在多线程环境下的执行效率和性能表现
【6月更文挑战第30天】Python的GIL是CPython中的全局锁,限制了多线程并行执行,尤其是在多核CPU上。GIL确保同一时间仅有一个线程执行Python字节码,导致CPU密集型任务时多线程无法充分利用多核,反而可能因上下文切换降低性能。然而,I/O密集型任务仍能受益于线程交替执行。为利用多核,开发者常选择多进程、异步IO或使用不受GIL限制的Python实现。在Web开发中,理解GIL对于优化并发性能至关重要。
61 0
|
3月前
|
数据采集 存储 安全
如何确保Python Queue的线程和进程安全性:使用锁的技巧
本文探讨了在Python爬虫技术中使用锁来保障Queue(队列)的线程和进程安全性。通过分析`queue.Queue`及`multiprocessing.Queue`的基本线程与进程安全特性,文章指出在特定场景下使用锁的重要性。文中还提供了一个综合示例,该示例利用亿牛云爬虫代理服务、多线程技术和锁机制,实现了高效且安全的网页数据采集流程。示例涵盖了代理IP、User-Agent和Cookie的设置,以及如何使用BeautifulSoup解析HTML内容并将其保存为文档。通过这种方式,不仅提高了数据采集效率,还有效避免了并发环境下的数据竞争问题。
如何确保Python Queue的线程和进程安全性:使用锁的技巧
|
1月前
|
Java C语言 Python
解析Python中的全局解释器锁(GIL):影响、工作原理及解决方案
解析Python中的全局解释器锁(GIL):影响、工作原理及解决方案
43 0
|
2月前
|
存储 算法 Java
关于python3的一些理解(装饰器、垃圾回收、进程线程协程、全局解释器锁等)
该文章深入探讨了Python3中的多个重要概念,包括装饰器的工作原理、垃圾回收机制、进程与线程的区别及全局解释器锁(GIL)的影响等,并提供了详细的解释与示例代码。
28 0
|
3月前
|
数据采集 Java Python
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
|
3月前
|
消息中间件 存储 安全
python多进程并发编程之互斥锁与进程间的通信
python多进程并发编程之互斥锁与进程间的通信
|
3月前
|
安全 Python
Python 中的全局解释器锁(GIL)详解
【8月更文挑战第24天】
89 0
|
3月前
|
Python
python 协程 自定义互斥锁
【8月更文挑战第6天】这段代码展示了如何在Python的异步编程中自定义一个互斥锁(`CustomMutex`类)。该类通过`asyncio.Lock`实现,并提供`acquire`和`release`方法来控制锁的获取与释放。示例还包含了使用此自定义锁的场景:两个任务(`task1`和`task2`)尝试按序获取锁执行操作,直观地演示了互斥锁的作用。这有助于理解Python协程中互斥锁的自定义实现及其基本用法。
|
5月前
|
安全 Java Python
GIL是Python解释器的锁,确保单个进程中字节码执行的串行化,以保护内存管理,但限制了多线程并行性。
【6月更文挑战第20天】GIL是Python解释器的锁,确保单个进程中字节码执行的串行化,以保护内存管理,但限制了多线程并行性。线程池通过预创建线程池来管理资源,减少线程创建销毁开销,提高效率。示例展示了如何使用Python实现一个简单的线程池,用于执行多个耗时任务。
45 6
|
4月前
|
安全 API Python
`multiprocessing`是Python的一个标准库,用于支持生成进程,并通过管道和队列、信号量、锁和条件变量等同步原语进行进程间通信(IPC)。
`multiprocessing`是Python的一个标准库,用于支持生成进程,并通过管道和队列、信号量、锁和条件变量等同步原语进行进程间通信(IPC)。