锁在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('主线程')
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()
'''此时使用互斥锁就使有用户没有抢到票了'''