进程互斥锁

基本概念

  • 临界资源: 一次仅允许一个进程使用的资源称为临界资源, 进程间采取互斥的方式, 共享临界资源
  • 进程互斥: 一个进程正在访问临界资源, 另一个要访问该资源的进程必须等待
  • 让并发变成串形, 牺牲了执行效率, 保证了数据的安全
  • 在程序并发执行时, 需要修改时使用

互斥锁的使用

# base_data--->{"ticket_num": 1}
# 模拟抢票软件
import json
import time
from multiprocessing import Process # 查看余票
def search(user):
with open('base_data', 'r', encoding='utf-8') as f:
dic = json.load(f)
ticket_num = dic.get('ticket_num')
print(f'用户{user}正在查看余票, 当前余票{ticket_num}张...') # 购买车票
def buy(user):
with open('base_data', 'r', encoding='utf-8') as f:
dic = json.load(f) # 阻塞
time.sleep(1) if dic.get('ticket_num') > 0:
dic['ticket_num'] -= 1
with open('base_data', 'w', encoding='utf-8') as f1:
json.dump(dic, f1)
print(f'用户[{user}]抢票成功!') else:
print(f'用户[{user}]抢票失败!') # 开始抢票
def run(user):
search(user)
buy(user) if __name__ == '__main__':
for i in range(10):
# 并发开启10个子进程
p = Process(target=run, args=(f'{i}',))
p.start()
'''
用户8正在查看余票, 当前余票1张...
用户6正在查看余票, 当前余票1张...
用户3正在查看余票, 当前余票1张...
用户0正在查看余票, 当前余票1张...
用户4正在查看余票, 当前余票1张...
用户2正在查看余票, 当前余票1张...
用户1正在查看余票, 当前余票1张...
用户7正在查看余票, 当前余票1张...
用户5正在查看余票, 当前余票1张...
用户9正在查看余票, 当前余票1张...
用户[8]抢票成功!
用户[6]抢票成功!
用户[3]抢票成功!
用户[4]抢票成功!
用户[1]抢票成功!
用户[5]抢票成功!
用户[2]抢票成功!
用户[0]抢票成功!
用户[7]抢票成功!
用户[9]抢票成功!
'''

使用进程锁将并发变成串行

# 模拟抢票软件
import json
import time
from multiprocessing import Process
from multiprocessing import Lock # 查看余票
def search(user):
with open('base_data', 'r', encoding='utf-8') as f:
dic = json.load(f)
ticket_num = dic.get('ticket_num')
print(f'用户[{user}]正在查看余票, 当前余票{ticket_num}张...') # 购买车票
def buy(user):
with open('base_data', 'r', encoding='utf-8') as f:
dic = json.load(f) time.sleep(1) if dic.get('ticket_num') > 0:
dic['ticket_num'] -= 1
with open('base_data', 'w', encoding='utf-8') as f1:
json.dump(dic, f1)
print(f'用户[{user}]抢票成功!') else:
print(f'用户[{user}]抢票失败!') # 开始抢票
def run(user, mutex):
# 上锁
mutex.acquire()
search(user)
buy(user)
# 解锁
mutex.release() if __name__ == '__main__':
# 调用Lock()类得到一个锁对象
mutex = Lock()
for i in range(10):
# 并发开启10个子进程
p = Process(target=run, args=(f'{i}', mutex))
p.start() '''
用户[0]正在查看余票, 当前余票1张...
用户[0]抢票成功!
用户[3]正在查看余票, 当前余票0张...
用户[3]抢票失败!
用户[2]正在查看余票, 当前余票0张...
用户[2]抢票失败!
用户[4]正在查看余票, 当前余票0张...
用户[4]抢票失败!
用户[8]正在查看余票, 当前余票0张...
用户[8]抢票失败!
用户[6]正在查看余票, 当前余票0张...
用户[6]抢票失败!
用户[7]正在查看余票, 当前余票0张...
用户[7]抢票失败!
用户[5]正在查看余票, 当前余票0张...
用户[5]抢票失败!
用户[1]正在查看余票, 当前余票0张...
用户[1]抢票失败!
用户[9]正在查看余票, 当前余票0张...
用户[9]抢票失败! '''

IPC

基本概念

  • inter-process communication 进程间通信
  • 进程间的数据是相互隔离的, 要想进行进程间的通信可以使用队列

队列

  • 进程间通信的一种方式, 支持多进程传入和取出数据
  • 遵循先进先出的原则
from multiprocessing import Queue

q = Queue(5)  # 队列中最多存放5个数据

# 填入数据
q.put('数据1')
q.put('数据2')
q.put('数据3')
q.put('数据4')
q.put('数据5')
# q.put('数据6') # 数据填满了继续存放, 程序会被卡住 # 查看队列是否填满
print(q.full()) # 队列满了, 则会会报错
# q.put_nowait('数据6') # 获取数据, 若队列中无数据可获取, 程序会卡住
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get()) # 队列中没有, 则会报错
# print(q.get_nowait()) # 判断队列是否为空
print(q.empty()) '''
True
数据1
数据2
数据3
数据4
数据5
True
'''

生产者消费者模型

基本概念

  • 生产者: 生产数据的
  • 消费者: 使用数据
  • 生产者消费者模型: 通过容器来解决生产者和消费者的之间的强耦合问题

代码实现

from multiprocessing import Process, Queue
import time # 定义生产者
def producer(q):
for i in range(5):
data = f'包子{i}'
q.put(data)
print(f'生产了{data}')
time.sleep(0.1) # 定义生产者
def consumer(q):
while True:
data = q.get()
print(f'吃了{data}') if __name__ == '__main__':
q = Queue()
p1 = Process(target=producer, args=(q,))
p2 = Process(target=consumer, args=(q,)) p1.start()
p2.start()
print('主') '''
主
生产了包子0
吃了包子0
生产了包子1
吃了包子1
生产了包子2
吃了包子2
生产了包子3
吃了包子3
生产了包子4
吃了包子4
'''

线程

基本概念

  • 进程是资源单位, 线程才是CPU的执行单位, 进行运算调度的最小单位
  • 线程包含在进程之中, 是进程中的实际运作单位
  • 线程开销要远小于进程, 可以节省内存资源
  • 线程之间共享进程中的数据
  • 线程pid为主进程pid

创建线程

from threading import Thread
import time # 方式一
def task():
print('线程开启')
time.sleep(1)
print('线程结束') if __name__ == '__main__':
t = Thread(target=task)
t.start() # 方式二
class MyThread(Thread):
def run(self):
print('线程开启')
time.sleep(1)
print('线程结束') if __name__ == '__main__':
t = MyThread()
t.start()

线程互斥锁

from threading import Thread, Lock
import time n = 100 def task(i):
print(f'线程{i}启动...')
global n
temp = n
time.sleep(0.1)
n = temp - 1
print(n) if __name__ == '__main__':
for i in range(10):
t = Thread(target=task, args=(i + 1,))
t.start() '''
线程1启动...
线程2启动...
线程3启动...
线程4启动...
线程5启动...
线程6启动...
线程7启动...
线程8启动...
线程9启动...
线程10启动...
99
99
99
99
99
99
99
99
99
99
'''
from threading import Thread, Lock
import time mutex = Lock() n = 100 def task(i):
mutex.acquire()
print(f'线程{i}启动...')
global n
temp = n
time.sleep(0.1)
n = temp - 1
print(n)
mutex.release() if __name__ == '__main__':
for i in range(10):
t = Thread(target=task, args=(i + 1,))
t.start() '''
线程1启动...
99
线程2启动...
98
线程3启动...
97
线程4启动...
96
线程5启动...
95
线程6启动...
94
线程7启动...
93
线程8启动...
92
线程9启动...
91
线程10启动...
90
'''

​

Python3 并发编程2的更多相关文章

  1. Python3 并发编程4

    目录 Event事件 线程池与进程池 基本概念 使用方法 和信号量的区别 协程(coroutine) 基本概念 实现方式 多线程爬取梨视频 Event事件 用来控制线程的执行 e.isSet()查看对 ...

  2. Python3 并发编程3

    目录 GIL全局解释器锁 基本概念 多线程的作用 死锁现象 递归锁 信号量 线程队列 GIL全局解释器锁 基本概念 global interpreter lock 全局解释器锁 GIL不是Python ...

  3. Python3 并发编程小练习

    实现基于TCP协议套接字,服务端实现接收客户端的连接并发 # server.py import socket from threading import Thread server = socket. ...

  4. Python3 并发编程1

    目录 操作系统发展 穿孔卡片 批处理 多道技术(单核) 并发与并行 进程 程序与进程 进程调度 进程的三个状态 同步和异步 阻塞与非阻塞 僵尸进程与孤儿进程 守护进程 Python中的进程操作 Pro ...

  5. Python3 与 C# 并发编程之~ 进程篇

      上次说了很多Linux下进程相关知识,这边不再复述,下面来说说Python的并发编程,如有错误欢迎提出- 如果遇到听不懂的可以看上一次的文章:https://www.cnblogs.com/dot ...

  6. Python3 与 C# 并发编程之~ 协程篇

      3.协程篇¶ 去年微信公众号就陆陆续续发布了,我一直以为博客也汇总同步了,这几天有朋友说一直没找到,遂发现,的确是漏了,所以补上一篇 在线预览:https://github.lesschina.c ...

  7. Python3 与 C# 并发编程之~进程先导篇

      在线预览:http://github.lesschina.com/python/base/concurrency/1.并发编程-进程先导篇.html Python3 与 C# 并发编程之- 进程篇 ...

  8. Python3 与 C# 并发编程之~ 线程篇

      2.线程篇¶ 在线预览:https://github.lesschina.com/python/base/concurrency/3.并发编程-线程篇.html 示例代码:https://gith ...

  9. asyncio:python3未来并发编程主流、充满野心的模块

    介绍 asyncio是Python在3.5中正式引入的标准库,这是Python未来的并发编程的主流,非常重要的一个模块.有一个web框架叫sanic,就是基于asyncio,语法和flask类似,使用 ...

随机推荐

  1. [RAM] FPGA的学习笔记——RAM

    1.RAM——随机存取存储器, 分为SRAM和DRAM. SRAM:存和取得速度快,操作简单.然而,成本高,很难做到很大.FPGA的片内存储器,就是一种SRAM,用来存放程序,以及程序执行过程中,产生 ...

  2. pat 1011 World Cup Betting(20 分)

    1011 World Cup Betting(20 分) With the 2010 FIFA World Cup running, football fans the world over were ...

  3. nyoj 77-开灯问题 (倍数遍历)

    77-开灯问题 内存限制:64MB 时间限制:3000ms 特判: No 通过数:13 提交数:24 难度:1 题目描述: 有n盏灯,编号为1~n,第1个人把所有灯打开,第2个人按下所有编号为2 的倍 ...

  4. React动画库

    npm i react-transition --save import {CSSTransition} from 'react-transition-group'

  5. keypress 和 blur 事件冲突的问题

    需求:点击需求:点击添加标签,出来input框,内容输入完成后点击enter键和blur时都可以执行提交标签的效果,提交时对内容进行判断,执行完成后清除input内的内容.如下图 问题:内容输入完成后 ...

  6. 根据本地ip获取地理位置,再根据地理位置,获取天气

    import json,requestsfrom urllib.request import urlopenfrom pyquery import PyQuery as pqfrom lxml imp ...

  7. HDFS之DataNode

    DataNode工作机制 1)一个数据块在datanode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳. 2)DataNode启动后 ...

  8. 2019-10-29:渗透测试,基础学习,sqlmap文件读取,写入,dnslog盲注作用,mssql手工注入,笔记

    sqlmap参数--file-read,从数据库服务器中读取文件--file-write,--file-dest,把文件上传到数据库服务器中 dnslog平台的学习和它在盲注中的应用1,判断注入点2, ...

  9. 【Luogu P1878】舞蹈课

    Luogu P1878 事实上这道题并不难,但我真没弄懂我手写堆为什么过不了.所以 STL大法好!!! 基本思路 对于每一对相邻异性,将他们的舞蹈技术的差插入一个堆 通过维护这个小根堆,每次就可以取得 ...

  10. 【NHOI2018】黑格覆盖

    [题目描述] 在一张由 M * N 个小正方形格子组成的矩形纸张上,有 k 个格子被涂成了黑色.给你一张由 m * n 个同样小正方形组成的矩形卡片,请问该卡片最多能一次性覆盖多少个黑格子? [输入数 ...