进程锁与线程
进程互斥锁
让并发变成串行,牺牲了执行效率,保证了数据的安全
在程序并发执行时,需要修改数据时使用。
from multiprocessing import lock
import json
from multiprocessing import process
import time
def search(user):
with open('data.txt','r',encoding='utf-8') as f:
dic=json.load(f)
print(f'{user}查看了余票,还剩{dic.get('ticekt_num')})
def buy(user):
with open('data.txt','r',encoding='utf-8')
dic=json.load(f)
time.sleep(1)
if dic.get('ticket_num')>0:
dic['ticket_num']-=1
with open('data','w',encoing='utf-8') as f:
json.dum(dic,f)
print(f'用户{user}抢票成功)
else:
print(f'{user}抢票失败')
def run(user,mutex):
search(user)
mutex.acquire()
buy(user)
mutex.release()
if __name__=='__main__':
# 调用Lock()类得到一个锁对象
mutex=lock()
# 加锁:
# mutex.acquire()
# 释放锁:
# mutex.release()
# 同时来10个用户抢票
for i in range(10):
# 并发开启10个子进程
p = Process(target=run, args=(f'用户{i}', mutex))
p.start()
队列:先进先出
相当于内存中产生一个队列空间,可以存放多个数据,但数据的顺序是由先进去的的排在前面。
from multiprocessimg import Queue
# 调用队列类,实例化队列对象 q
q=Queue(5) # 若传参队列中可以存放5个数据
q=Queue() # 若不传参,队列中可以存放无限大的数据,前提硬件能更得上
# put添加数据,若队列中的数据满了,则卡住
q.put(1)
print('进入数据1')
q.put(2)
print('进入数据2')
q.put(3)
print('进入数据3')
q.put(4)
print('进入数据4')
q.put(5)
print('进入数据5')
# 查看队列是否满了
print(q.full()) # True
# 判断队列是否为空
print(q.empty()) # False
# 添加数据,若队列满了,则会报错
# q.put_nowait(6)
# q.get(): 获取的数据遵循 "先进先出",若队列中无数据可取,也会卡住
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
堆栈:先进后出
相当于内存中产生了一个队列空间,可以存放多个数据,但数据的顺序是由先进去的排在前么
IPC进程间通信
进程间数据是相互隔离的,若想实现进程间通信,可以利用队列。
from multiprocessing import process
from multiprocessing improt Queue
def test1(q):
data='数据hello'
q.put(data)
print('进程1开始添加数据到队列中')
def test2(q)
data=q.get()`
print(f'进程2从队列中获取数据{data})
if __name__=='__main__':
q=Queue
p1=process(target=test1,args=(q,))
p2=process(target=test1,args=(q,))
p1.start()
p2.start()
print('主')
生产者于消费者
from multiprocessing import Queue, Process
import time
# 生产者
def producer(name, food, q): # 生产名, 食物, 队列
for i in range(3):
data = food, i
msg = f'用户{name}开始制作{data}'
print(msg)
q.put(data)
time.sleep(0.1)
# 消费者
def consumer(name, q):
while True:
data = q.get()
if not data:
break
print(f'用户{name}开始吃{data}')
if __name__ == '__main__':
q = Queue()
# 创造生产者
p1 = Process(target=producer, args=('tank', '油条', q))
p2 = Process(target=producer, args=('华农兄弟', '竹鼠', q))
# 生产消费者
c1 = Process(target=consumer, args=('egon', q))
c2 = Process(target=consumer, args=('jason', q))
p1.start()
p2.start()
c1.daemon = True
c2.daemon = True
c1.start()
c2.start()
p1.join()
# p2.join()
print('主')
线程
什么是线程
线程于进程都是虚拟单位,目的是为了更好的描述某种事物。
进程:资源单位
线程:执行单位
开器一个进程,一定会由一个线程,线程才是真正的执行者。
为什么要使用线程
节省内存资源
开器进程:
- 开辟一个名称空空间,每开器一个进程都会占用一份内存
- 会自带一个线程
开器线程:
- 一个进程可以开启多个线程
- 线程的开销远小于进程
注意
线程不能实现并行,线程只能实现并发,进程可以实现并行
from threading impor thread
impor time
# 开启线程方式一:
def task()
print('线程开启')
time.sleep(1)
print('线程结束')
if __name__=='__main__':
t=Thread(target=task)
t.start()
class MyThread(Thread):
def run(self):
print('线程开启')
t=MyThread()
t.start()
线程对象的属性
def task():
print(f'线程开启{current_thread().name}') # 获取线程号
time.sleep(1)
print(f'线程结束{current_thread().name}')
if __name__=='__main__':
t=Thread(target=task)
t.start()
print(t.isAlive()) #判断线程是否存在
print('主')
线程互斥锁
线程之间数据是共享的
from threading import Thread
impot time
x=100
def task():
print('开启线程')
time.sleep(1)
global x
x=200
print('关闭线程')
t=Thread(target=task)
t.start()
t.join()
print(x)
print('主')