并发编程之互斥锁

互斥锁

锁在IT界都是非常重要的,不但在Python中出现,尤其是数据库中得锁更多,
比如:表锁、行锁、悲观锁、乐观锁、进程锁、互斥锁、递归锁、可重入锁、死锁等。

互斥锁是什么?

将并发变成串行 虽然牺牲了程序的执行效率 但是保证了数据的安全

互斥锁概念

同一时间运行一个进程上一把锁,就是Lock。那么我们加锁的意义在哪呢?
加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,
即串行的修改。虽然我们的程序运行速度是慢了,但牺牲速度却保证了数据安全

同一时间允许多个进程上多把锁 就是[信号量Semaphore]
信号量是锁的变形:实际实现是 计数器+锁,同时允许多个进程上锁

互斥锁的作用

互斥锁Lock:互斥锁就是进程的相互排斥
谁先抢到自由,谁就上锁该资源内容,这样做可以保证数据的同步性。
注意:多个锁一起上锁,不开锁会造成死锁,上锁和释放锁是一对

什么时候使用互斥锁

多个程序同时操作一份数据的时候容易产生数据错乱
为了避免数据错乱,我们需要使用互斥锁

如何使用互斥锁

如何使用?
    导入模块 form multiprocessing import Process,Lock
    lock = Lock()   # 变量名创建一个锁
    lock.acquire()  # 上锁
    lock.release()  # 释放锁
上锁谁抢到谁使用,其他人等着使用完才能使用

'''
锁相关的知识
	行锁:针对行数据加锁 同一时间只能一个人操作
	表锁:针对表数据加锁 同一时间只能一个人操作
	锁的应用范围很广 但是核心都是为了保证数据的安全!!!
'''

做一个简单案例试试

	'简单案例'
from multiprocessing import Process,Lock
import time
'''使用锁的目的就是为了保证安全'''
def task(i,lock):
    lock.acquire()  # 上锁
    print('进程%s进来了' % i)
    time.sleep(1)
    print('进程%s走了' % i)
    lock.release()  # 释放锁
    '''只要上锁了,就一定别忘了最后释放锁,否则的话,别的进程永远进不来'''

    '''
        加上锁就一定好吗?虽然保证了数据的安全,但是呢执行效率降低了,
        所以只适用于相应适配的场景,
    '''

# 使用锁就是为了安全
if __name__ == '__main__':
    lock = Lock()
    ll = []
    for i in range(3):
        p = Process(target=task,args =(i+1,lock))
        p.start()
        ll.append(p)

    for j in ll:
        j.join()

    print('主线程')

模拟简易版12306抢票、查票、买票

import time, random, json
from multiprocessing import Process, Lock
import multiprocessing
# 导入模块

写入系统票数
pl = {'ticket_num':5}
with open(r'data.json','w',encoding='utf-8')as f:
	json.dump(pl,f,ensure_ascii=False)


'查票'
def search(name):
    with open(r'data.json','r',encoding='utf-8')as f:
        data = json.load(f)

    print(f"{name}查看票,目前剩余:{data.get('ticket_num')}")


'买票'
def buy(name):
    # 先查询票数
    with open(r'data.json','r',encoding='utf-8')as f:
        data = json.load(f)

    '模拟网络延迟'
    time.sleep(random.randint(1,3))  #

    '判断当前是否有票'
    if data.get('ticket_num') > 0:
        data['ticket_num'] -= 1
        with open(r'data.json','w',encoding='utf-8')as f1:
            json.dump(data,f1,ensure_ascii=False)

        print(f"{name}抢票成功!")
    else:
        print(f"{name}很抱歉暂无票了")

def run(name):
    search(name)
    buy(name)

if __name__ == '__main__':
    for i in range(10):
        p = Process(target=run,args=(f"用户{i}",))
        p.start()

'''这里输出结果是10个人都抢到票了,所以在这种情况下我们就得用互斥锁!'''

print('============以下使用了互斥锁的代码================')

'查票'
def search(name):
    with open(r'data.json','r',encoding='utf-8')as f:
        data = json.load(f)

    print(f"{name}正在查票,当前剩余:{data.get('ticket_num')}张票")



'买票'
def buy(name):
    # 需要先查询是否有票
    with open(r'data.json','r',encoding='utf-8')as f:
        data = json.load(f)

    # 模拟延迟
    time.sleep(random.randint(1,3))

    # 判断当前是否有票
    if data.get('ticket_num') > 0:
        data['ticket_num'] -= 1
        with open(r'data.json','w',encoding='utf-8')as f1:
            json.dump(data,f1,ensure_ascii=False)
        print(f"用户{name},购票成功!")
    else:
        print(f"用户{name},sorry,当前暂未有票哦")

def run(name,lock):
    search(name)
    # 只需要把买票环节变成串行即可
    lock.acquire()  # 上锁
    buy(name)
    lock.release()  # 释放锁

if __name__ == '__main__':
	'互斥锁在主进程中产生一把 交给多个子进程使用'
	'''
    Lock互斥锁,进程之间数据是不共享的
    但是Lock对象底层是通过socket来互相发送数据,不管多少进程,都是同一个Lock锁
    '''
    lock = Lock()  # 创建一把锁
    for i in range(10):
        p = Process(target=run,args=(f"用户:{i}", lock))
        p.start()

'''此时使用互斥锁就使有用户没有抢到票了'''

你可能感兴趣的:(网络编程,python)