进程锁
什么是进程锁;
进程锁是一种在多线程和多进程程序中使用的同步机制。它可以控制在同一时刻只有一个线程或进程可以访问共享资源,以避免竞态条件和数据损坏。
进程锁通常使用两种方式实现:互斥锁和读写锁。互斥锁用于保护共享资源,只允许一个线程或进程访问该资源。读写锁则允许多个线程或进程同时访问共享资源,但只有一个线程或进程可以进行写操作,以确保数据的一致性和完整性。
进程锁是并发编程中非常重要的机制,它可以有效地保护共享资源,避免数据损坏和不一致的问题。在实际应用中,开发人员需要根据不同场景选择适当的进程锁,并合理使用它们以确保程序的正确运行。
锁在IT界都是非常重要的,不但在Python中出现,尤其是数据库中得锁更多,比如:表锁、行锁、悲观锁、乐观锁、进程锁、互斥锁、递归锁、可重入锁、死锁等
关键字:lock,acquire,release
"""关键字:lock:锁,lock.acquire:上锁, lock.release 释放锁"""
from multiprocessing import Process, Lock
import time
def task(i, lock):
lock.acquire() # 添加锁
print('进程%s来了' % i)
time.sleep(3)
print('进程走了%s' % i)
lock.release() # 释放锁
"""上锁之后一定要释放出来,不然别的程序永远进不来"""
if __name__ == '__main__':
lock = Lock() # 得到一把锁
for i in range(4):
p = Process(target=task, args=(i+1, lock))
p.start()
"""打印结果:进程1来了
进程走了1
进程3来了
进程走了3
进程2来了
进程走了2
进程4来了
进程走了4"""
进程号
当我们知道进程号之后,可以通过进程号来结束进程的执行kill+进程号
def task(n):
print('执行的进程号%s' % os.getpid())
# os.getpid() 写在哪个进程里面就会输出哪个进程的进程号
print('task进程的父进程号%s' % os.getppid())
time.sleep(2)
if __name__ == '__main__':
p = Process(target=task, args=('kk',))
p.start()
print('子进程号', p.pid)
print('主进程号', os.getppid())
time.sleep(3)
进程之间数据隔离问题
这两个进程没有通讯,
def task():
global n
n = 2
print('子进程')
if __name__ == '__main__':
p = Process(target=task, )
p.start()
print('主进程的数是',n)
'''输出的结果为:主进程的数是 100
子进程'''
队列
我们学过数据结构:链衣,表链衣,单链表,双链表,循环链表,栈,队列,树,二叉树,图等数据结构。
队列的特点是先进先出
栈是先进后出
使用队列
·关键字Queue:
from multiprocessing import Queue
q = Queue(3)
q.put('ll1')
q.put('ll2')
q.put('ll3')
print(q.get())
print(q.get())
print(q.get())
"""输出结果:ll1
ll2
ll3
"""
超出报错
get_nowait与block=False是一样的
timeout:超时的时间, 如果在指定的时间内,没有放进去,就会直接报错
from multiprocessing import Queue
q = Queue(2)
q.put('执行结果1')
q.put('执行结果2')
q.put('执行结果3', block=False)
# block=False 当队列里的数据超出时,直接报错
print(q.get())
print(q.get())
报错信息:Traceback (most recent call last):
File "D:\pythonProject\day37\锁.py", line 6, in <module>
q.put('执行结果3', block=False)
File "D:\python38\lib\multiprocessing\queues.py", line 84, in put
raise Full
queue.Full
q.qsize队列的大小
q.empty 队列里是存在,存在为True,不存在为False
生产者消费者模型
我们在并发编程中使用生产者与消费者模型模式,能够解决大部分的并发问题,该模式通过平衡生产者线程与消费者线程的工作能力提高整体的数据处理速度。
from multiprocessing import Queue,Process
def producer(q,food):
# 生产10个产品
for i in range(10):
q.put('生成了%s个包子' % i)
def consumer(q):
while True:
res = q.get()
print(res)
if res is None:
break
if __name__ == '__main__':
q = Queue(10)
p = Process(target=producer, args=(q, '包子'))
p.start()
c1 = Process(target=consumer, args=(q,))
c1.start()
p.join()
输出结果:生成了0个包子
生成了1个包子
生成了2个包子
生成了3个包子
生成了4个包子
生成了5个包子
生成了6个包子
生成了7个包子
生成了8个包子
生成了9个包子
None
q.put(None)
线程
在一个进程中,线程就是必须存在的,至少要有一个线程来执行任务
一个进程中可以有多个线程,在一个进程中可有开启多个线程来执行任务
进程和线程都是有操作系统调度的
进程是操作系统分配资源的基本单位,线程是操作系统执行的最小单位
开启线程与进程的操作是一样的
from threading import Thread
def task():
print('执行线程')
if __name__ == '__main__':
t = Thread(target=task)
t.start()
"""使用线程的方法和进程的方法一致"""
守护线程
在一个进程中只有一个线程也被称为主线程,其他线程称为子线程
例如当A进程结束时,那么B进程也会结束。
from threading import Thread
import time
def task(name):
print('hello%s'% name)
time.sleep(3)
print('你好%s'% name)
if __name__ == '__main__':
t = Thread(target=task, args=('coco', ))
t.daemon = True
t.start()
time.sleep(1)
print('主程序结束') # print('主程序结束')
"""使用线程的方法和进程的方法一致"""