python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池

时间:2022-08-15 00:09:03

0、承上

   什么是线程?

    CPU调度的最小单位。

    线程是进程的必要组成单位。

  主线程:

    程序开始运行的时候,就产生了一个主线进程来运行这个程序。

  子线程:

    是由主线程开启的其他线程。

·  各线程之间的工作关系

    异步的

    数据共享的

  GIL锁:Cpython解释器中有一把锁,锁的是线程。

  线程是CPU调度的最小单位

  

1、线程的开启

   线程不能在外界干扰下结束,而是等待程序执行完毕才结束的,主线程要等待子线程的结束而结束

 

python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
 1 from threading import Thread, currentThread
 2 
 3 def t_func():
 4     global n
 5     n -= 1
 6     print(currentThread())
 7 
 8 if __name__ == '__main__':
 9     n = 100
10     t_lst = []
11     for i in range(100):
12         t = Thread(target=t_func)
13         t.start()
14         t_lst.append(t)
15         print(t.ident, t.name, t.is_alive())
16     for t in t_lst:
17         t.join()
18     print(n)
线程的开启
python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
D:\Python36\python.exe E:/Python/草稿纸0.py
<Thread(Thread-1, started 20124)>
20124 Thread-1 True
<Thread(Thread-2, started 20128)>
20128 Thread-2 True
<Thread(Thread-3, started 20132)>
20132 Thread-3 True
<Thread(Thread-4, started 20136)>
20136 Thread-4 True
<Thread(Thread-5, started 20140)>
20140 Thread-5 True
<Thread(Thread-6, started 20144)>
20144 Thread-6 True
<Thread(Thread-7, started 20148)>
20148 Thread-7 True
<Thread(Thread-8, started 20152)>
20152 Thread-8 True
<Thread(Thread-9, started 20156)>
20156 Thread-9 True
<Thread(Thread-10, started 20160)>
20160 Thread-10 True
<Thread(Thread-11, started 20164)>
20164 Thread-11 True
<Thread(Thread-12, started 20168)>
20168 Thread-12 True
<Thread(Thread-13, started 20172)>
20172 Thread-13 True
<Thread(Thread-14, started 20176)>
20176 Thread-14 True
<Thread(Thread-15, started 20180)>
20180 Thread-15 True
<Thread(Thread-16, started 20184)>
20184 Thread-16 True
<Thread(Thread-17, started 20188)>
20188 Thread-17 True
<Thread(Thread-18, started 20192)>
20192 Thread-18 True
<Thread(Thread-19, started 20196)>
20196 Thread-19 True
<Thread(Thread-20, started 20200)>
20200 Thread-20 True
<Thread(Thread-21, started 20204)>
20204 Thread-21 True
<Thread(Thread-22, started 20208)>
20208 Thread-22 True
<Thread(Thread-23, started 20212)>
20212 Thread-23 True
<Thread(Thread-24, started 20216)>
20216 Thread-24 True
<Thread(Thread-25, started 20220)>
20220 Thread-25 True
<Thread(Thread-26, started 20224)>
20224 Thread-26 True
<Thread(Thread-27, started 20228)>
20228 Thread-27 True
<Thread(Thread-28, started 20232)>
20232 Thread-28 True
<Thread(Thread-29, started 20236)>
20236 Thread-29 True
<Thread(Thread-30, started 20240)>
20240 Thread-30 True
<Thread(Thread-31, started 20244)>
20244 Thread-31 True
<Thread(Thread-32, started 20248)>
20248 Thread-32 True
<Thread(Thread-33, started 20252)>
20252 Thread-33 False
<Thread(Thread-34, started 20256)>
20256 Thread-34 True
<Thread(Thread-35, started 20260)>
20260 Thread-35 True
<Thread(Thread-36, started 20264)>
20264 Thread-36 False
<Thread(Thread-37, started 20268)>
20268 Thread-37 True
<Thread(Thread-38, started 20272)>
20272 Thread-38 True
<Thread(Thread-39, started 20276)>
20276 Thread-39 False
<Thread(Thread-40, started 20280)>
20280 Thread-40 True
<Thread(Thread-41, started 20284)>
20284 Thread-41 True
<Thread(Thread-42, started 20288)>
20288 Thread-42 True
<Thread(Thread-43, started 20292)>
20292 Thread-43 False
<Thread(Thread-44, started 20296)>
20296 Thread-44 True
<Thread(Thread-45, started 20300)>
20300 Thread-45 False
<Thread(Thread-46, started 20304)>
20304 Thread-46 True
<Thread(Thread-47, started 20308)>
20308 Thread-47 True
<Thread(Thread-48, started 20312)>
20312 Thread-48 True
<Thread(Thread-49, started 20316)>
20316 Thread-49 False
<Thread(Thread-50, started 20320)>
20320 Thread-50 False
<Thread(Thread-51, started 20324)>
20324 Thread-51 True
<Thread(Thread-52, started 20328)>
20328 Thread-52 True
<Thread(Thread-53, started 20332)>
20332 Thread-53 True
<Thread(Thread-54, started 20336)>
20336 Thread-54 True
<Thread(Thread-55, started 20340)>
20340 Thread-55 True
<Thread(Thread-56, started 20344)>
20344 Thread-56 True
<Thread(Thread-57, started 20348)>
20348 Thread-57 True
<Thread(Thread-58, started 20352)>
20352 Thread-58 True
<Thread(Thread-59, started 20356)>
20356 Thread-59 True
<Thread(Thread-60, started 20360)>
20360 Thread-60 True
<Thread(Thread-61, started 20364)>
20364 Thread-61 True
<Thread(Thread-62, started 20368)>
20368 Thread-62 False
<Thread(Thread-63, started 20372)>
20372 Thread-63 True
<Thread(Thread-64, started 20376)>
20376 Thread-64 True
<Thread(Thread-65, started 20380)>
20380 Thread-65 True
<Thread(Thread-66, started 20384)>
20384 Thread-66 True
<Thread(Thread-67, started 20388)>
20388 Thread-67 True
<Thread(Thread-68, started 20392)>
20392 Thread-68 False
<Thread(Thread-69, started 20396)>
20396 Thread-69 True
<Thread(Thread-70, started 20400)>
20400 Thread-70 True
<Thread(Thread-71, started 20404)>
20404 Thread-71 True
<Thread(Thread-72, started 20408)>
20408 Thread-72 False
<Thread(Thread-73, started 20412)>
20412 Thread-73 True
<Thread(Thread-74, started 20416)>
20416 Thread-74 True
<Thread(Thread-75, started 20420)>
20420 Thread-75 True
<Thread(Thread-76, started 20424)>
20424 Thread-76 True
<Thread(Thread-77, started 20428)>
20428 Thread-77 False
<Thread(Thread-78, started 20432)>
20432 Thread-78 True
<Thread(Thread-79, started 20436)>
20436 Thread-79 True
<Thread(Thread-80, started 20440)>
20440 Thread-80 True
<Thread(Thread-81, started 20444)>
20444 Thread-81 True
<Thread(Thread-82, started 20448)>
20448 Thread-82 True
<Thread(Thread-83, started 20452)>
20452 Thread-83 True
<Thread(Thread-84, started 20456)>
20456 Thread-84 True
<Thread(Thread-85, started 20460)>
20460 Thread-85 True
<Thread(Thread-86, started 20464)>
20464 Thread-86 False
<Thread(Thread-87, started 20468)>
20468 Thread-87 True
<Thread(Thread-88, started 20472)>
20472 Thread-88 True
<Thread(Thread-89, started 20476)>
20476 Thread-89 True
<Thread(Thread-90, started 19584)>
19584 Thread-90 True
<Thread(Thread-91, started 19588)>
19588 Thread-91 True
<Thread(Thread-92, started 6800)>
6800 Thread-92 True
<Thread(Thread-93, started 19568)>
19568 Thread-93 True
<Thread(Thread-94, started 18904)>
18904 Thread-94 True
<Thread(Thread-95, started 19604)>
19604 Thread-95 True
<Thread(Thread-96, started 19608)>
19608 Thread-96 True
<Thread(Thread-97, started 19612)>
19612 Thread-97 True
<Thread(Thread-98, started 19620)>
19620 Thread-98 True
<Thread(Thread-99, started 19616)>
19616 Thread-99 True
<Thread(Thread-100, started 19624)>
19624 Thread-100 True
0

Process finished with exit code 0
结果

  

2、守护线程

   主进程守护  会等待主进程的代码执行结束而结束。

python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
import time
from multiprocessing import Process

def func1():
    time.sleep(3)
    print('in func1')

def func2():
    while True:
        time.sleep(0.5)
        print('in func2')
if __name__ == '__main__':
    Process(target=func1).start()
    t = Process(target=func2)
    t.daemon = True
    t.start()
    print('主进程')
进程守护
python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
D:\Python36\python.exe E:/Python/草稿纸0.py
主进程
in func1

Process finished with exit code 0
结果

  

   主线程守护  会等待主线程执行完毕才结束,主线程会等待所有子进程结束而结束。

python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
 1 import time
 2 from threading import Thread
 3 
 4 def func1():
 5     time.sleep(3)
 6     print('in func1')
 7 
 8 def func2():
 9     while True:
10         time.sleep(0.5)
11         print('in func2')
12 
13 if __name__ == '__main__':
14     Thread(target=func1).start()
15     t = Thread(target=func2)
16     t.setDaemon(True)
17     t.start()
18     print('主线程')
守护线程
python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
D:\Python36\python.exe E:/Python/草稿纸0.py
主线程
in func2
in func2
in func2
in func2
in func2
in func2
in func1

Process finished with exit code 0
结果

  

3、锁

python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
 1 from threading import Thread
 2 
 3 def t_func():
 4     global n
 5     n -= 1
 6 
 7 if __name__ == '__main__':
 8     n = 200000
 9     t_lst = []
10     for i in range(200000):
11         t = Thread(target=t_func)
12         t.start()
13         t_lst.append(t)
14     for t in t_lst:
15         t.join()
16     print(n)
锁1
python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
D:\Python36\python.exe E:/Python/草稿纸0.py
0

Process finished with exit code 0
结果

 

 

python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
 1 import threading
 2 
 3 balance = 0
 4 def change_it(n):
 5     global balance
 6     balance = balance + n
 7     balance = balance - n
 8 
 9 def run_thread(n, lock):
10     for i in range(150000):
11         change_it(n)
12 
13 lock = threading.Lock()
14 t1 = threading.Thread(target=run_thread, args=(5, lock))
15 t2 = threading.Thread(target=run_thread, args=(5, lock))
16 t1.start()
17 t2.start()
18 t1.join()
19 t2.join()
20 print(balance)
线程之间的数据不安全
python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
D:\Python36\python.exe E:/Python/草稿纸0.py
-5

Process finished with exit code 0
结果(异常)
python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
D:\Python36\python.exe E:/Python/草稿纸0.py
0

Process finished with exit code 0
结果(正常)

 

 

python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
 1 import threading
 2 
 3 balance = 0
 4 def change_it(n):
 5     global balance
 6     balance = balance + n
 7     balance = balance - n
 8 
 9 def run_thread(n, lock):
10     for i in range(150000):
11         with lock:
12             change_it(n)
13 
14 lock = threading.Lock()
15 t1 = threading.Thread(target=run_thread, args=(5, lock))
16 t2 = threading.Thread(target=run_thread, args=(5, lock))
17 t1.start()
18 t2.start()
19 t1.join()
20 t2.join()
21 print(balance)
线程加锁

 

python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
D:\Python36\python.exe E:/Python/草稿纸0.py
0

Process finished with exit code 0
结果

 

 

4、死锁

  互斥锁和递归锁的区别:

    互斥锁在同一个线程中连续acquire一次以上就会死锁

    递归锁在同一个线程中可以连续的acquire多次而不会发生死锁

  普遍:递归锁可以替代互斥锁来解决死锁现象

 

  实际上:  递归锁的解决死锁实际上是牺牲了时间和空间的

    死锁本质上来讲是一种逻辑上的错误

    递归锁没有从本质上解决死锁的问题

 

   互斥锁

python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
1 from threading import Lock
2 lock = Lock()
3 lock.acquire()
4 print(123)
5 lock.release()
互斥锁
python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
D:\Python36\python.exe E:/Python/草稿纸0.py
123

Process finished with exit code 0
结果

 

 

  递归锁

python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
1 from threading import RLock
2 
3 lock = RLock()
4 lock.acquire()
5 lock.acquire()
6 print(123)
7 lock.release()
递归锁
python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
D:\Python36\python.exe E:/Python/草稿纸0.py
123

Process finished with exit code 0
结果

 

 

  吃面问题(死锁)

python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
 1 from threading import Thread, Lock
 2 
 3 def eat1(name, fork_lock, noodle_lock):
 4     fork_lock.acquire()
 5     print(f'{name}拿到叉子了')
 6     noodle_lock.acquire()
 7     print(f'{name}拿到面条了')
 8     print(f'{name}吃面')
 9     noodle_lock.release()
10     fork_lock.release()
11 
12 def eat2(name, fork_lock, noodke_lock):
13     noodke_lock.acquire()
14     print(f'{name}拿到面条了')
15     fork_lock.acquire()
16     print(f'{name}拿到叉子了')
17     print(f'{name}吃面')
18     fork_lock.release()
19     noodke_lock.release()
20 
21 fork_lock = Lock()
22 noodle_lock = Lock()
23 Thread(target=eat1, args=('alex', fork_lock, noodle_lock)).start()
24 Thread(target=eat2, args=('wusir', fork_lock, noodle_lock)).start()
25 Thread(target=eat1, args=('yuan', fork_lock, noodle_lock)).start()
26 Thread(target=eat2, args=('jin', fork_lock, noodle_lock)).start()
吃面问题
python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
D:\Python36\python.exe E:/Python/草稿纸0.py
alex拿到叉子了
alex拿到面条了
alex吃面
wusir拿到面条了
wusir拿到叉子了
wusir吃面
yuan拿到叉子了
yuan拿到面条了
yuan吃面
jin拿到面条了
jin拿到叉子了
jin吃面

Process finished with exit code 0
结果

 

 

  递归锁解决死锁现象

python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
 1 from threading import Thread, RLock
 2 
 3 def eat1(name, fork_lock, noodle_lock):
 4     fork_lock.acquire()
 5     print(f'{name}拿到叉子了')
 6     noodle_lock.acquire()
 7     print(f'{name}拿到面了')
 8     print(f'{name}吃面')
 9     noodle_lock.release()
10     fork_lock.release()
11 
12 def eat2(name, fork_lock, noodle_lock):
13     noodle_lock.acquire()
14     print(f'{name}拿到面条了')
15     fork_lock.acquire()
16     print(f'{name}拿到叉子了')
17     print(f'{name}吃面')
18     fork_lock.release()
19     noodle_lock.release()
20 
21 noodle_lock = fork_lock = RLock()
22 Thread(target=eat1, args=('alex', fork_lock, noodle_lock)).start()
23 Thread(target=eat2, args=('wusir', fork_lock, noodle_lock)).start()
24 Thread(target=eat1, args=('yuan', fork_lock, noodle_lock)).start()
25 Thread(target=eat2, args=('jin', fork_lock, noodle_lock)).start()
递归锁
python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
D:\Python36\python.exe E:/Python/草稿纸0.py
alex拿到叉子了
alex拿到面了
alex吃面
wusir拿到面条了
wusir拿到叉子了
wusir吃面
yuan拿到叉子了
yuan拿到面了
yuan吃面
jin拿到面条了
jin拿到叉子了
jin吃面

Process finished with exit code 0
结果

 

 

python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
 1 import time
 2 from threading import Thread, Lock
 3 
 4 def eat1(name, lock):
 5     lock.acquire()
 6     print(f'{name}拿到叉子了')
 7     print(f'{name}拿到面条了')
 8     print(f'{name}吃面')
 9     lock.release()
10 
11 def eat2(name, lock):
12     lock.acquire()
13     print(f'{name}拿到面条了')
14     time.sleep(1)
15     print(f'{name}拿到叉子了')
16     print(f'{name}吃面')
17     lock.release()
18 
19 noodle_fork_lock = Lock()
20 Thread(target=eat1, args=('alex', noodle_fork_lock)).start()
21 Thread(target=eat2, args=('wusir', noodle_fork_lock)).start()
22 Thread(target=eat1, args=('yuan', noodle_fork_lock)).start()
23 Thread(target=eat2, args=('jin', noodle_fork_lock)).start()
简化
python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池python_线程的开启、守护线程、锁、死锁、事件、定时器、条件、队列、池
D:\Python36\python.exe E:/Python/草稿纸0.py
alex拿到叉子了
alex拿到面条了
alex吃面
wusir拿到面条了
wusir拿到叉子了
wusir吃面
yuan拿到叉子了
yuan拿到面条了
yuan吃面
jin拿到面条了
jin拿到叉子了
jin吃面

Process finished with exit code 0
结果

 

 

5、事件

 未完待续。。。 

 

6、定时器

  未完待续。。。 

  

7、条件

  未完待续。。。 

  

8、队列

  未完待续。。。 

  

9、池

  未完待续。。。