【Python Threading 学习笔记】6、锁lock


往期内容:

1、什么是多线程?

2、添加线程

3、join功能

4、Queue功能

5、不一定有效率GIL

0x00 关于线程锁lock

多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。

而使用lock就可以在不同线程使用同一共享内存时,能够确保线程之间互不影响。

0x01 不使用lock锁的情况

job1:全局变量A的值每次加1,循环7次并打印

1
2
3
4
5
def job1(): # 全局变量A的值每次加1,循环7次并打印
global A
for i in range(7):
A += 1
print('job1',A)

job2:全局变量A的值每次加10,循环7次并打印

1
2
3
4
5
def job2():# 全局变量A的值每次加10,循环7次并打印
global A
for i in range(7):
A += 10
print('job2',A)

main:定义两个线程并执行job1和job2

1
2
3
4
5
6
7
def main(): # 定义两个线程并执行job1和job2
t1 = threading.Thread(target=job1)
t2 = threading.Thread(target=job2)
t1.start()
t2.start()
t1.join()
t2.join()

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import threading


def job1(): # 全局变量A的值每次加1,循环7次并打印
global A
for i in range(7):
A += 1
print('job1',A)


def job2():# 全局变量A的值每次加10,循环7次并打印
global A
for i in range(7):
A += 10
print('job2',A)


def main(): # 定义两个线程并执行job1和job2
t1 = threading.Thread(target=job1)
t2 = threading.Thread(target=job2)
t1.start()
t2.start()
t1.join()
t2.join()


if __name__ == '__main__':
A = 0
main()

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# python 6_lock.py
job1 1
job1 2
job1 3
job1 4
job1 5job2 15
job2 
job1 2625
job2
job1 36 37
job2 
47
job2 57
job2 67
job2 77

可以看到不使用lock的时候,打印的结果很混乱。

0x02 使用lock的情况

使用lock的方法是, 在每个线程执行运算修改共享内存之前,执行lock.acquire()将共享内存上锁, 确保当前线程执行时,内存不会被其他线程访问,执行运算完毕后,使用lock.release()将锁打开, 保证其他的线程可以使用该共享内存。

为job1和job2加锁:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def job1(): # 全局变量A的值每次加1,循环7次并打印
global A,lock
lock.acquire() # 上锁
for i in range(7):
A += 1
print('job1',A)
lock.release() # 开锁


def job2():# 全局变量A的值每次加10,循环7次并打印
global A,lock
lock.acquire() # 上锁
for i in range(7):
A += 10
print('job2',A)
lock.release() # 开锁

在程序入口处定义一个lock

1
2
3
4
if __name__ == '__main__':
lock = threading.Lock()
A = 0
main()

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import threading


def job1(): # 全局变量A的值每次加1,循环7次并打印
global A,lock
lock.acquire()
for i in range(7):
A += 1
print('job1',A)
lock.release()


def job2():# 全局变量A的值每次加10,循环7次并打印
global A,lock
lock.acquire()
for i in range(7):
A += 10
print('job2',A)
lock.release()


def main(): # 定义两个线程并执行job1和job2
t1 = threading.Thread(target=job1)
t2 = threading.Thread(target=job2)
t1.start()
t2.start()
t1.join()
t2.join()


if __name__ == '__main__':
lock = threading.Lock()
A = 0
main()

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# python 6_lock.py
job1 1
job1 2
job1 3
job1 4
job1 5
job1 6
job1 7
job2 17
job2 27
job2 37
job2 47
job2 57
job2 67
job2 77

从运行结果来看,使用lock后,一个线程一个线程的执行完,两个线程之间互不影响。
至此,整个【Python Threading 学习笔记】系列更新完毕。

代码项目地址:https://github.com/teamssix/Python-Threading-study-notes
参考文章:
1、https://www.jianshu.com/p/05b6a6f6fdac
2、https://morvanzhou.github.io/tutorials/python-basic/threading


文章作者: Teams Six
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Teams Six !
评论
 上一篇
【漏洞笔记】X-Frame-Options Header未配置 【漏洞笔记】X-Frame-Options Header未配置
0x00 概述漏洞名称:X-Frame-Options Header未配置 风险等级:低危 问题类型:管理员设置问题 0x01 漏洞描述X-Frame-Options HTTP 响应头是用来给浏览器指示允许一个页面可否在<忽略fram
2019-11-19
下一篇 
【Python Threading 学习笔记】5、不一定有效率GIL 【Python Threading 学习笔记】5、不一定有效率GIL
往期内容: 1、什么是多线程? 2、添加线程 3、join功能 4、Queue功能 0x00 关于GILGIL的全称是Global Interpreter Lock(全局解释器锁),来源是python设计之初的考虑,为了数据安全所做的决定。
2019-11-04
  目录