0%

python | 多线程与锁

在看这篇文章之前请先看

本文采取例子进行循序渐进。

多线程无锁

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 asyncio
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import threading
import random

lock = threading.Lock()

num = 0


def add():
global num
for i in range(1000000):
num += 1


def sub():
global num
for i in range(1000000):
num -= 1


if __name__ == '__main__':
sub1 = threading.Thread(target=add)
sub2 = threading.Thread(target=sub)

sub1.start()
sub2.start()

sub1.join()
sub2.join()

print(num)

每次输出都不一样

多线程有锁

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
35
36
37
38
39
import asyncio
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import threading
import random

lock = threading.Lock()

num = 0


def add():
global num
for i in range(1000000):
lock.acquire()
num += 1
lock.release()


def sub():
global num
for i in range(1000000):
lock.acquire()
num -= 1
lock.release()


if __name__ == '__main__':

sub1 = threading.Thread(target=add)
sub2 = threading.Thread(target=sub)

sub1.start()
sub2.start()

sub1.join()
sub2.join()

print(num)

输出 0

线程池无锁

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
import asyncio
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import threading
import random

lock = threading.Lock()

num = 0


def add():
global num
for i in range(1000000):
num += 1


def sub():
global num
for i in range(1000000):
num -= 1


if __name__ == '__main__':
task_list = []
pool = ThreadPoolExecutor(max_workers=2)
task = pool.submit(add)
task_list.append(task)
task2 = pool.submit(sub)
task_list.append(task2)

print(num)

每次输出都不一样。

线程池有锁

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
35
36
import asyncio
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import threading
import random

lock = threading.Lock()

num = 0


def add():
global num
for i in range(1000000):
lock.acquire()
num += 1
lock.release()


def sub():
global num
for i in range(1000000):
lock.acquire()
num -= 1
lock.release()


if __name__ == '__main__':
task_list = []
pool = ThreadPoolExecutor(max_workers=2)
task = pool.submit(add)
task_list.append(task)
task2 = pool.submit(sub)
task_list.append(task2)

print(num)

发现输出也不是 0

这是因为,多线程在运行的时候,主线程没有等待多线程运行完就直接运行了主线程,所以,我们要加一个判断,等多线程运行完了,再运行主线程。

线程池有锁 优化

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
35
36
37
38
39
import asyncio
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
import threading
import random

lock = threading.Lock()

num = 0


def add():
global num
for i in range(1000000):
lock.acquire()
num += 1
lock.release()


def sub():
global num
for i in range(1000000):
lock.acquire()
num -= 1
lock.release()


if __name__ == '__main__':
task_list = []
pool = ThreadPoolExecutor(max_workers=2)
task = pool.submit(add)
task_list.append(task)
task2 = pool.submit(sub)
task_list.append(task2)

for result in as_completed(task_list):
data = result.result()

print(num)

输出 0

请我喝杯咖啡吧~