互斥锁
多个进程直接虽然数据不共享,但是它们共享同一套文件系统(或者同一个打印终端)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| from multiprocessing import Process import time
def task(name): print('%s 1'%name) time.sleep(1) print('%s 2'%name) time.sleep(1) print('%s 3' % name)
if __name__ == '__main__': # args传递的参数必须是元组的形式 for i in range(3): p = Process(target=task, args=('子进程%s'%i,)) p.start()
print('主进程。。。。')
''' 主进程。。。。 子进程0 1 子进程1 1 子进程2 1 子进程0 2 子进程1 2 子进程2 2 子进程0 3 子进程1 3 子进程2 3 此时数据发生错乱,三个进程都占据打印终端的输出,这样数据容易出现问题 '''
|
互斥锁(来把锁)
- 从multiprocessing引入Lock
- 初始化锁 mutex = Lock()
- 给子进程的触发函数传入锁对象mutex
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| from multiprocessing import Process,Lock import time
def task(name,mutex): mutex.acquire() print('%s 1'%name) time.sleep(1) print('%s 2'%name) time.sleep(1) print('%s 3' % name) mutex.release()
if __name__ == '__main__': # args传递的参数必须是元组的形式 for i in range(3): mutex=Lock() p = Process(target=task, args=('子进程%s'%i,mutex)) p.start()
print('主进程。。。。')
''' 主进程。。。。 子进程0 1 子进程1 1 子进程2 1 子进程0 2 子进程1 2 子进程2 2 子进程0 3 子进程1 3 子进程2 3 '''
|
模拟抢票
多个进程共享同一文件,我们可以把文件当数据库,用多个进程模拟多个人执行抢票任务
新建文件db.txt的内容为:{“count”:1}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| from multiprocessing import Process import json import time
def search(name): time.sleep(1) # 模拟网络延迟 dic = json.load(open('db.txt',encoding='utf-8')) print('<%s>查看剩余票数[%s]'%(name,dic['count']))
def get(name): time.sleep(1) dic = json.load(open('db.txt', encoding='utf-8')) if dic['count']>0: dic['count']-=1 time.sleep(3) json.dump(dic,open('db.txt','w',encoding='utf-8')) print('<%s 购票成功>'%name)
def task(name): search(name) get(name)
if __name__ == '__main__': for i in range(10): p = Process(target=task,args=('路人%s'%i,)) p.start()
''' <路人0>查看剩余票数[1] <路人2>查看剩余票数[1] <路人1>查看剩余票数[1] <路人3>查看剩余票数[1] <路人4>查看剩余票数[1] <路人5>查看剩余票数[1] <路人6>查看剩余票数[1] <路人7>查看剩余票数[1] <路人8>查看剩余票数[1] <路人9>查看剩余票数[1] <路人0 购票成功> <路人2 购票成功> <路人1 购票成功> <路人3 购票成功> <路人4 购票成功> <路人5 购票成功> <路人6 购票成功> <路人7 购票成功> <路人8 购票成功> <路人9 购票成功>
并发的执行查看同一个文件,于是都看到了剩余1张票,最后都购票成功于是 打起来了。。。。 '''
|
加锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| from multiprocessing import Process,Lock import json import time
def search(name): time.sleep(1) # 模拟网络延迟 dic = json.load(open('db.txt',encoding='utf-8')) print('<%s>查看剩余票数[%s]'%(name,dic['count']))
def get(name): time.sleep(1) dic = json.load(open('db.txt', encoding='utf-8')) if dic['count']>0: dic['count']-=1 time.sleep(3) json.dump(dic,open('db.txt','w',encoding='utf-8'))
print('<%s 购票成功>'%name) def task(name,mutex): mutex.acquire() search(name) get(name) mutex.release()
if __name__ == '__main__': mutex = Lock() for i in range(10): p = Process(target=task,args=('路人%s'%i,mutex)) p.start() ''' <路人0>查看剩余票数[1] <路人0 购票成功> <路人2>查看剩余票数[0] <路人1>查看剩余票数[0] <路人3>查看剩余票数[0] <路人4>查看剩余票数[0] <路人5>查看剩余票数[0] <路人6>查看剩余票数[0] <路人7>查看剩余票数[0] <路人8>查看剩余票数[0] <路人9>查看剩余票数[0] '''
|
上述有一个问题必须等第一个人购票了其他人才能查票
做如下修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| def task(name,mutex):
search(name)
mutex.acquire() get(name) mutex.release()
''' <路人0>查看剩余票数[1] <路人1>查看剩余票数[1] <路人2>查看剩余票数[1] <路人3>查看剩余票数[1] <路人4>查看剩余票数[1] <路人5>查看剩余票数[1] <路人6>查看剩余票数[1] <路人7>查看剩余票数[1] <路人8>查看剩余票数[1] <路人9>查看剩余票数[1] <路人0 购票成功> '''
|
互斥锁和join的区别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| from multiprocessing import Process,Lock import json import time
def search(name): time.sleep(1) # 模拟网络延迟 dic = json.load(open('db.txt',encoding='utf-8')) print('<%s>查看剩余票数[%s]'%(name,dic['count']))
def get(name): time.sleep(1) dic = json.load(open('db.txt', encoding='utf-8')) if dic['count']>0: dic['count']-=1 time.sleep(3) json.dump(dic,open('db.txt','w',encoding='utf-8')) print('<%s 购票成功>'%name) else: print('<%s 购票失败>' % name) def task(name): search(name) get(name)
if __name__ == '__main__': for i in range(10): p = Process(target=task,args=('路人%s'%i,)) p.start() p.join()
''' 去掉锁后改用join虽然保证了串行,影响了整个的查询效率变慢了 <路人0>查看剩余票数[1] <路人0 购票成功> <路人1>查看剩余票数[0] <路人1 购票失败> <路人2>查看剩余票数[0] <路人2 购票失败> <路人3>查看剩余票数[0] <路人3 购票失败> <路人4>查看剩余票数[0] <路人4 购票失败> <路人5>查看剩余票数[0] <路人5 购票失败> <路人6>查看剩余票数[0] <路人6 购票失败> <路人7>查看剩余票数[0] <路人7 购票失败> <路人8>查看剩余票数[0] <路人8 购票失败> <路人9>查看剩余票数[0] <路人9 购票失败> '''
|