python-day33(线程)

一. 线程(threading模块)

  线程是CPU的最小执行单位,进程: 资源单位

  multiprocess模块完全模仿了threading模块的接口,二者在使用层面,有很大的相似性

 1 import time
 2 from threading import Thread
 3 #多线程并发,是不是看着和多进程很类似
 4 def func(n):
 5     time.sleep(1)
 6     print(n)
 7 
 8 #并发效果,1秒打印出了所有的数字
 9 for i in range(10):
10     t = Thread(target=func,args=(i,))
11     t.start()
多线程简单实现

  1. 线程的创建

 1 from threading import Thread
 2 import time
 3 def sayhi(name):
 4     time.sleep(2)
 5     print('%s say hello' %name)
 6 
 7 if __name__ == '__main__':
 8     t=Thread(target=sayhi,args=('太白',))
 9     t.start()
10     print('主线程')
方式一
 1 import time
 2 from threading import Thread
 3 class Sayhi(Thread):
 4     def __init__(self,name):
 5         super().__init__()
 6         self.name=name
 7     def run(self):
 8         time.sleep(2)
 9         print('%s say hello' % self.name)
10 
11 
12 if __name__ == '__main__':
13     t = Sayhi('太白')
14     t.start()
15     print('主线程')
方式二

  2. 线程的方法

 1 from threading import Thread
 2 import time
 3 def sayhi(name):
 4     time.sleep(2)
 5     print('%s say hello' %name)
 6 
 7 if __name__ == '__main__':
 8     t=Thread(target=sayhi,args=('太白',))
 9     t2=Thread(target=sayhi,args=('alex',))
10     t.start()
11     t2.start()
12     t.join()  #因为这个线程用了join方法,主线程等待子线程的运行结束
13 
14     print('主线程')
15     print(t.is_alive())  #所以t这个线程肯定是执行结束了,结果为False
16     print(t2.is_alive()) #有可能是True,有可能是False,看子线程和主线程谁执行的快
17     '''
18     egon say hello
19     主线程
20     False
21     '''
join方法
 1 Thread实例对象的方法
 2   # isAlive(): 返回线程是否活动的。
 3   # getName(): 返回线程名。
 4   # setName(): 设置线程名。
 5 
 6 threading模块提供的一些方法:
 7   # threading.currentThread(): 返回当前的线程变量。
 8   # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
 9   # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
10 
11 
12 from threading import Thread
13 import threading
14 from multiprocessing import Process
15 import os
16 
17 def work():
18     import time
19     time.sleep(3)
20     print(threading.current_thread().getName())
21 
22 if __name__ == '__main__':
23     #在主进程下开启线程
24     t=Thread(target=work)
25     t.start()
26 
27     print(threading.current_thread())#主线程对象
28     print(threading.current_thread().getName()) #主线程名称
29     print(threading.current_thread().ident) #主线程ID
30     print(threading.get_ident()) #主线程ID
31     print(threading.enumerate()) #连同主线程在内有两个运行的线程
32     print(threading.active_count())
33     print('主线程/主进程')
34 
35     '''
36     打印结果:
37     <_MainThread(MainThread, started 14104)>
38     MainThread
39     14104
40     14104
41     [<_MainThread(MainThread, started 14104)>, <Thread(Thread-1, started 17976)>]
42     2
43     主线程/主进程
44     Thread-1
45     '''
其他方法

二. 线程和进程效率对比

 1 from threading import Thread
 2 from multiprocessing import Process
 3 import os
 4 import time
 5 def work():
 6     print('hello')
 7 
 8 if __name__ == '__main__':
 9     s1 = time.time()
10     #在主进程下开启线程
11     t=Thread(target=work)
12     t.start()
13     t.join()
14     t1 = time.time() - s1
15     print('进程的执行时间:',t1)
16     print('主线程/主进程')
17     '''
18     打印结果:
19     hello
20     进程的执行时间: 0.0
21     主线程/主进程
22     '''
23 
24     s2 = time.time()
25     #在主进程下开启子进程
26     t=Process(target=work)
27     t.start()
28     t.join()
29     t2 = time.time() - s2
30     print('线程的执行时间:', t2)
31     print('主线程/主进程')
32     '''
33     打印结果:
34     hello
35     线程的执行时间: 0.5216977596282959
36     主线程/主进程
37     '''
效率比较,线程快

三. 查看子线程和主线程是否在同一进程

# 查看子线程和主线程是否在同一个进程中
from threading import Thread
import os
def fun():
    print('子线程的pid',os.getpid()) #获得当前 线程pid
if __name__ == '__main__':
    t = Thread(target=fun,)
    t.start()
    print('主线程的pid',os.getpid()) #获得当前 pid  
#结果是一样的,是同一进程里

四. 线程之间的数据是共享的

from threading import Thread
def fun():
    global a
    a -= 1
a = 10
if __name__ == '__main__':

    t = Thread(target=fun,)
    t.start()
    t.join() # 加join 等待t 结束
    print(a) # 9 证明数据是共享的

五. 验证多线程共享资源造成的数据不安全

扫描二维码关注公众号,回复: 4306666 查看本文章
# 验证多线程共享资源造成的数据不安全的问题
from threading import Thread
import time
def fun():
    global a
    t = a
    time.sleep(0.00001)
    t -= 1
    a = t
a = 20
if __name__ == '__main__':
    l = []
    for i in range(20):
        t = Thread(target=fun,)
        l.append(t)
        t.start()
    for i in l :
        i.join()
    print(a) # 18 

六. 加锁解决共享数据不安全的问题

  锁(互斥锁\同步锁) #Lock,解决数据共享是数据不安全的问题,

      但同时也牺牲了效率

  

 1 from threading import Thread,Lock
 2 import time
 3 def fun(l):
 4     l.acquire()
 5     global a
 6     t = a
 7     time.sleep(0.1)
 8     t -= 1
 9     a = t
10     l.release()
11 a = 20
12 if __name__ == '__main__':
13     l = []
14     lock = Lock()
15     for i in range(20):
16         t = Thread(target=fun ,args=(lock,))
17         l.append(t)
18         t.start()
19     for i in l:
20         i.join()
21     print(a)
# 加锁解决共享数据不安全的问题

七. 死锁现象

  死锁现象: 双方互相等待对方释放对方手里拿到的那个锁

  

 1 from threading import Thread ,Lock
 2 import time
 3 
 4 def fun1(lock_A,lock_B):
 5     lock_A.acquire()
 6     time.sleep(1)
 7 
 8     print('A抢到了锁a')
 9     lock_B.acquire()
10     print('A抢到了锁b')
11     lock_B.release()
12     lock_A.release()
13 def fun2(lock_A,lock_B):
14     lock_B.acquire()
15     print('B抢到了b锁')
16     lock_A.acquire()
17     print('B抢到了a锁')
18     lock_A.release()
19     lock_B.release()
20 if __name__ == '__main__':
21     lock_A = Lock()
22     lock_B = Lock()
23     t1 = Thread(target=fun1,args=(lock_A,lock_B))
24     t2 = Thread(target=fun2,args=(lock_A,lock_B))
25     t1.start()
26     t2.start()
死锁现象

八. 解决死锁, 使用递归锁

  同样是互斥,里面存着个计数器

  进程的死锁和线程的是一样的,而且一般情况下进程之间是数据不共享的,

不需要加锁,由于线程是对全局的数据共享的,所以对于全局的数据进行操作的时候,要加锁.

递归锁解决死锁现象

九. 守护线程

  守护线程: 主线程等着进程中所有非守护线程的结束,才算结束

  守护进程: 主进程代码结束, 守护进程跟着结束

十. 信号量

十一. 事件

猜你喜欢

转载自www.cnblogs.com/Thui/p/10045995.html