最近复习了下多线程中锁的知识,发现网络上好多篇博文介绍多线程中锁的概念时都很含糊其辞,一笔就带过了。而且更要命的地方在于几乎都将锁与资源放在一起介绍,让我看得云里雾里的,看得是十分头疼。这篇文章就单独说下锁的基本概念,其余高级应用可以去那些博客看看。
首先要明确的一点就是:锁跟资源其实是不相干的。多线程中的锁是一个全局变量实例,它的作用等同于一个标志位。其具体用法为,在全部需要加锁的资源处,在修改前对锁进行锁定,修改完后释放锁。当一个线程对锁进行锁定后,其余线程执行对锁进行锁定的操作时就会进入阻塞状态,直至锁被释放,然后由多个线程对该锁进行抢夺。抢夺到锁的线程将锁进行锁定,然后对资源进行修改,其余未抢夺到锁的线程则继续处于阻塞状态。
用代码来阐述就是
import time
from datetime import datetime
from threading import Thread, Lock
Resource = 0
ResourceLock = Lock()
def modify():
ResourceLock.acquire()
print(f'child thread 1 get lock time: '
f'{datetime.now().strftime("%H:%M:%S")}')
time.sleep(3)
global Resource
Resource += 3
print(f'child thread 1 modify resource time: '
f'{datetime.now().strftime("%H:%M:%S")} resource: {Resource}')
print(f'child thread 1 release lock time: '
f'{datetime.now().strftime("%H:%M:%S")}')
ResourceLock.release()
def modify_2():
time.sleep(1)
global Resource
Resource += 100
print(f'child thread 2 modify resource time: '
f'{datetime.now().strftime("%H:%M:%S")} resource: {Resource}')
def modify_3():
ResourceLock.acquire()
print(f'child thread 3 get lock time: '
f'{datetime.now().strftime("%H:%M:%S")}')
time.sleep(1)
global Resource
Resource += 2
print(f'child thread 3 modify resource time: '
f'{datetime.now().strftime("%H:%M:%S")} resource: {Resource}')
print(f'child thread 3 release lock time: '
f'{datetime.now().strftime("%H:%M:%S")}')
ResourceLock.release()
def main():
child_thread_1 = Thread(target=modify)
child_thread_2 = Thread(target=modify_2)
child_thread_3 = Thread(target=modify_3)
child_thread_1.start()
child_thread_2.start()
child_thread_3.start()
time.sleep(6)
print(f'main thread exit time: '
f'{datetime.now().strftime("%H:%M:%S")}')
if __name__ == '__main__':
main()
其运行结果为
child thread 1 get lock time: 14:32:13
child thread 2 modify resource time: 14:32:14 resource: 100
child thread 1 modify resource time: 14:32:16 resource: 103
child thread 1 release lock time: 14:32:16
child thread 3 get lock time: 14:32:16
child thread 3 modify resource time: 14:32:17 resource: 105
child thread 3 release lock time: 14:32:17
main thread exit time: 14:32:19
可以看到子线程1即使抢占了锁,子线程2还是可以修改资源变量。而与此同时,因为子线程1抢占了锁,子线程3进入了阻塞状态,直至子线程1释放了锁。