python进程锁和线程锁_浅谈线程锁和进程锁

​ 在python的多线程和多进程中,当我们需要对多线程或多进程的共享资源或对象进行修改操作时,往往会出现因cpu随机调度而导致结果和我们预期不一致的问题,

线程举例:

from threading import Thread,Lock

x = 0

def task():

global x

for i in range(200000):

x = x+1

'''

假设

t1 的 x刚拿到0 保存状态 就被切了

t2 的 x拿到0 进行+1 1

t1 又获得运行了 x = 0 +1 1

思考:一共加了几次1? 加了两次1 真实运算出来的数字本来应该+2 实际只+1

这就产生了数据安全问题.

'''

if __name__ == '__main__':

t1 = Thread(target=task)

t2 = Thread(target=task)

t3 = Thread(target=task)

t1.start()

t2.start()

t3.start()

t1.join()

t2.join()

t3.join()

print(x)

479261

from multiprocessing import Process,Lock

import json,time,os

def search():

time.sleep(1) # 模拟网络io

with open('db.txt',mode='rt',encoding='utf-8') as f:

res = json.load(f)

print(f'还剩{res["count"]}')

def get():

with open('db.txt',mode='rt',encoding='utf-8') as f:

res = json.load(f)

time.sleep(1) # 模拟网络io

if res['count'] > 0:

res['count'] -= 1

with open('db.txt',mode='wt',encoding='utf-8') as f:

json.dump(res,f)

print(f'进程{os.getpid()} 抢票成功')

time.sleep(1.5) # 模拟网络io

else:

print('票已经售空啦!!!!!!!!!!!')

def task():

search()

get()

if __name__ == '__main__':

for i in range(5):

p = Process(target=task)

p.start()

还剩1

还剩1

还剩1

还剩1

还剩1

进程6292 抢票成功

进程10604 抢票成功

进程19280 抢票成功

进程272 抢票成功

进程12272 抢票成功

这时就需要对线程或者进程加锁,以保证一个线程或进程在对共享对象进行修改时,其他的线程或进程无法访问这个对象,直至获取锁的线程的操作执行完毕后释放锁。所以,锁在多线程和多进程中起到一个同步的作用,以保护每个线程和进程必要操作的完整执行。

#线程锁

from threading import Thread,Lock

x = 0

mutex = Lock()

def task():

global x

mutex.acquire()

for i in range(200000):

x = x+1

mutex.release()

if __name__ == '__main__':

t1 = Thread(target=task)

t2 = Thread(target=task)

t3 = Thread(target=task)

t1.start()

t2.start()

t3.start()

t1.join()

t2.join()

t3.join()

print(x)

600000

from multiprocessing import Process,Lock

import json,time,os

def search():

time.sleep(1) # 模拟网络io

with open('db.txt',mode='rt',encoding='utf-8') as f:

res = json.load(f)

print(f'还剩{res["count"]}')

def get():

with open('db.txt',mode='rt',encoding='utf-8') as f:

res = json.load(f)

# print(f'还剩{res["count"]}')

time.sleep(1) # 模拟网络io

if res['count'] > 0:

res['count'] -= 1

with open('db.txt',mode='wt',encoding='utf-8') as f:

json.dump(res,f)

print(f'进程{os.getpid()} 抢票成功')

time.sleep(1.5) # 模拟网络io

else:

print('票已经售空啦!!!!!!!!!!!')

def task(lock):

search()

# 锁住

lock.acquire()

get()

lock.release()

# 释放锁头

if __name__ == '__main__':

lock = Lock() # 写在主进程是为了让子进程拿到同一把锁.

for i in range(15):

p = Process(target=task,args=(lock,))

p.start()

# p.join()

# 进程锁 是把锁住的代码变成了串行

# join 是把所有的子进程变成了串行

# 为了保证数据的安全,串行牺牲掉效率.

还剩1

还剩1

还剩1

还剩1

还剩1

进程16868 抢票成功

票已经售空啦!!!!!!!!!!!

票已经售空啦!!!!!!!!!!!

票已经售空啦!!!!!!!!!!!

票已经售空啦!!!!!!!!!!!

你可能感兴趣的:(python进程锁和线程锁)