共享全局变量资源竞争的解决方法?
互斥锁 & 死锁
一个线程写入 一个线程读取 没问题 如果两个线程都写入呢?
互斥锁
当多个线程几乎同时修改某一个共享数据的时候 需要进行同步控制
某个线程要更改共亨数据时,先将其锁定,此时资源的状态为’锁定’
其他线程不能改变 直到该线程释放资源,将资源的状态变成’非锁定’
其他的线程才能再次锁定该资源 互斥锁保证了每次只有一个线程进行
写操作 从而保证了多线程情况下数据的正确性。
创建锁
mutex = threading.Lock()
锁定
mutex.acquire()
解锁
mutex.release()
一个互斥锁 mutex = threading.Lock()
import threading
import time
# 创建一个互斥锁 默认是没有上锁的
mutex = threading.Lock()
num = 0
def demo1(nums):
global num
# 加锁
mutex.acquire()
for i in range(nums):
num += 1
# 解锁
mutex.release()
print("demo1---num:%d" % num)
def demo2(nums):
global num
mutex.acquire()
for i in range(nums):
num += 1
mutex.release()
print("demo2---num:%d" % num)
def main():
t1 = threading.Thread(target=demo1,args=(1000000,))
t2 = threading.Thread(target=demo2,args=(1000000,))
t1.start()
t2.start()
time.sleep(1)
print("main---num:%d" % num)
执行结果:
可重入的锁 mutex = threading.RLock()
import threading
import time
num = 0
# 创建一个互斥锁 默认是没有上锁的 Lock只能加一把锁解一把锁
# mutex = threading.Lock()
# 可重入的锁
mutex = threading.RLock()
def demo1(nums):
global num
# 加锁
mutex.acquire()
mutex.acquire()
for i in range(nums):
num += 1
# 解锁
mutex.release()
mutex.release()
print('demo1---num:%d' % num)
def demo2(nums):
global num
mutex.acquire()
for i in range(nums):
num += 1
mutex.release()
print('demo2---num:%d' % num)
def main():
t1 = threading.Thread(target=demo1,args=(100000,))
t2 = threading.Thread(target=demo2,args=(100000,))
t1.start()
t2.start()
time.sleep(1)
print('main--num:%d'% num)
if __name__ == '__main__':
main()
死锁
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
import threading
import time
mutexA = threading.Lock()
mutexB = threading.Lock()
class MyThread1(threading.Thread):
def run(self):
# 对mutexA 上锁
mutexA.acquire()
# mutexA 上锁后,延时1秒 等待另外那个线程把mutexB 上锁
print(self.name+'---do1--up---')
time.sleep(1)
# 此时会堵塞 因为这个mutexB已经被另外的线程抢先上锁了
mutexB.acquire()
print(self.name+'---do1--down---')
mutexB.release()
# 对mutexA 解锁
mutexA.release()
class MyThread2(threading.Thread):
def run(self):
# 对mutexB 上锁
mutexB.acquire()
# mutexB 上锁后 延时1秒 等待另外那个钱程 把mutexA上锁
print(self.name+'---do2---up---')
time.sleep(1)
# 此时会堵塞 因为这个mutexA已经被另外的线程抢行上锁了
mutexA.acquire()
print(self.name+'---do2---down---')
mutexA.release()
# 对mutexB解锁
mutexB.release()
if __name__ == '__main__':
t1 = MyThread1()
t2 = MyThread2()
t1.start()
t2.start()
执行结果:
避免死锁
程序设计时要尽量避免
添加超时时间等