互斥锁

进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,

竞争带来的结果就是错乱,如何控制,就是加锁处理

part1:多个进程共享同一打印终端

#并发运行,效率高,但竞争同一打印终端,带来了打印错乱
from multiprocessing import Process,Lock
import os,time,random

def task(mutex):
    print("111111")
    time.sleep(2)
    print("222222")
    time.sleep(2)
    print("333333")

if __name__ == "__main__":
    mutex = Lock()
    p1 = Process(target=task,args=(mutex,))
    p2 = Process(target=task,args=(mutex,))
    p3 = Process(target=task,args=(mutex,))
    p1.start()
    p2.start()
    p3.start()
#运行结果
#111111
#111111
#111111
#222222
#222222
#222222
#333333
#333333
#333333

加锁后由并发变成了串行

from multiprocessing import Process,Lock
import os,time,random

def task(mutex):
    mutex.acquire()
    print("111111")
    time.sleep(2)
    print("222222")
    time.sleep(2)
    print("333333")
    mutex.release()

if __name__ == "__main__":
    mutex = Lock()
    p1 = Process(target=task,args=(mutex,))
    p2 = Process(target=task,args=(mutex,))
    p3 = Process(target=task,args=(mutex,))
    p1.start()
    p2.start()
    p3.start()
#运行结果
#111111
#222222
#333333
#111111
#222222
#333333
#111111
#222222
#333333

互斥锁与join的区别

join是等一个进程运行完后下一个进程才运行,而互斥锁是进程都执行了,不过这个任务每次都只能有一个进程执行,谁抢到谁运行。

且join是全局的,一个进程没完不会开启下一个进程,互斥锁可以局部进行,专门为某一个任务加锁。

#有一个名为db.txt的文件,内容为{"count": 1}
def search(): #查票
    with open('db.txt',encoding='utf-8') as f:
        dic=json.load(f)
        print('%s 剩余票数 %s' %(os.getpid(),dic['count']))

def get(): #买票
    with open('db.txt',encoding='utf-8') as read_f:
        dic=json.load(read_f)

    if dic['count'] > 0:
        dic['count']-=1
        time.sleep(random.randint(1,3)) #模拟手速+网速
        with open('db.txt','w',encoding='utf-8') as write_f:
            json.dump(dic,write_f)
            print('%s 抢票成功' %os.getpid())

def task():
    search()
    get()

if __name__ == '__main__':
    for i in range(20): #模拟20人买票
        p=Process(target=task)
        p.start()
        p.join()
#运行结果-使用join其他人不能够查票
8596 剩余票数 1
8596 抢票成功
4092 剩余票数 0
9088 剩余票数 0
7508 剩余票数 0
10424 剩余票数 0
3216 剩余票数 0
15432 剩余票数 0
6136 剩余票数 0
5440 剩余票数 0
7744 剩余票数 0
14744 剩余票数 0
14768 剩余票数 0
15812 剩余票数 0
7140 剩余票数 0
10076 剩余票数 0
15364 剩余票数 0
8332 剩余票数 0
16180 剩余票数 0
3052 剩余票数 0
8592 剩余票数 0

 使用锁的方式

def search():
    with open('db.txt',encoding='utf-8') as f:
        dic=json.load(f)
        print('%s 剩余票数 %s' %(os.getpid(),dic['count']))

def get():
    with open('db.txt',encoding='utf-8') as read_f:
        dic=json.load(read_f)

    if dic['count'] > 0:
        dic['count']-=1
        time.sleep(random.randint(1,3)) #模拟手速+网速
        with open('db.txt','w',encoding='utf-8') as write_f:
            json.dump(dic,write_f)
            print('%s 抢票成功' %os.getpid())

def task(mutex):
    search()
    mutex.acquire()
    get()  # 只为买票加锁
    mutex.release()


if __name__ == '__main__':
    mutex=Lock()
    for i in range(20):
        p=Process(target=task,args=(mutex,))
        p.start()
#结果-并不影响查票,但买票只能一个一个买
10356 剩余票数 1
15436 剩余票数 1
10008 剩余票数 1
14496 剩余票数 1
5668 剩余票数 1
15884 剩余票数 1
7288 剩余票数 1
7308 剩余票数 1
15740 剩余票数 1
152 剩余票数 1
12260 剩余票数 1
14988 剩余票数 1
15396 剩余票数 1
15696 剩余票数 1
1036 剩余票数 1
7632 剩余票数 1
15392 剩余票数 1
14600 剩余票数 1
12408 剩余票数 1
16168 剩余票数 1
10356 抢票成功

  

线程互斥锁

线程之间数据共享,如果多个线程同时修改数据,会产生意外的结果

from threading import Thread,Lock
import time
n=100

def task():
    global n
    temp=n
    time.sleep(0.1) #模仿处理时间
    n=temp-1




if __name__ == '__main__':
    # mutex=Lock()
    t_l=[]
    for i in range(100):
        t=Thread(target=task)
        t_l.append(t)
        t.start()
    for t in t_l:
        t.join()
    print(n)
# 运行结果-他们几乎是同时拿到了数据,进行处理,但拿到的是相同的数据
99

加锁

from threading import Thread,Lock
import time
n=100

def task(): #可以不传递mutex,线程共享资源,而进程必须要传过去
    global n
    mutex.acquire()
    temp=n
    time.sleep(0.1)
    n=temp-1
    mutex.release()
  #另外一种写法
  
# global n
  # with mutex:
  # temp=n
  # time.sleep(0.1)
  # n=temp-1

if __name__ == '__main__': mutex=Lock() t_l=[] for i in range(100): t=Thread(target=task) t_l.append(t) t.start() for t in t_l: t.join() print(n) #执行结果-进行加锁,使他们不能同时拿到数据,只有在一个进程结束之后才可以拿 #0

 死锁与递归锁

所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程

 

posted @ 2017-12-04 17:21  瓜田月夜  阅读(90)  评论(0)    收藏  举报