Python--线程

进程与线程的区别:

1. 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;

2. 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;

3. 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信号等),某进程内的线程在其他进程不可见;

4. 调度和切换:线程上下文切换比进程上下文切换要快得多。

多线程:

多线程工作实例1:实现类似并发执行的效果,实际上并非并发,是多个线程间进行上下文的切换

 1 import threading
 2 import time
 3 def run(n):
 4     print("task ",n )
 5     time.sleep(2)
 6     print("task done",n)
 7 start_time = time.time()
 8 t_objs = [] #存线程实例
 9 for i in range(50):
10     t = threading.Thread(target=run,args=("t-%s" %i ,)) # 实例化一个线程,指定线程执行run函数,args传参数
11     t.start() # 启动实例化的线程
12     t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里
13 for t in t_objs: #循环线程实例列表
14     t.join() # .join:等待线程执行完毕
15 print("----------all threads has finished...")
16 print("cost:",time.time() - start_time)

程序中,启动了50个线程,每个线程在执行run方法时,均sleep两秒,在程序结束时,实际上总体时间仅仅用了2秒多。

守护线程:设置子线程为守护线程时,当主线程结束时,子线程即结束,不会等待子线程执行完毕

守护线程实例:

 1 import  threading,time # 导入模块
 2 
 3 def run(n): # 定义线程执行的函数
 4     print("is task:", n, threading.current_thread())
 5     time.sleep(2)
 6     print("task done",n, threading.current_thread())
 7 
 8 start_time = time.time() # 标记开始时间
 9 
10 for i in range(20): # 启动20个线程
11     t = threading.Thread(target=run, args=("t-%s" % i,))
12     t.setDaemon(True) # .setDaemon设置线程为守护线程
13     t.start() # 启动线程
14 
15 time.sleep(1) # 主线程sleep,程序执行时间完全取决于此sleep时间,与子线程的sleep无关
16 print("------threading runing done",threading.current_thread(),threading.active_count())
17 print("cost:",time.time()- start_time) # 计算程序结束时间

程序中,以守护线程的形式启动20个子线程,在主线程结束时子线程同时结束,即使子线程尚未执行完毕。程序总花费时间为1s多。

线程锁:

  由于多线程是同时执行的,多线程在修改同一个数据时,会出现修改后的数据不正确的情况。可以使用线程锁实现线程串行修改数据。

 

 1 import  threading,time # 导入模块
 2 
 3 def run(): # 线程执行函数
 4     lock.acquire() # 加锁
 5     global num # 将num设置为全局变量
 6     num += 1
 7     print(num)
 8     time.sleep(1)
 9     lock.release() # 解锁
10 
11 num = 0
12 t_obj = [] # 线程列表
13 lock = threading.Lock() # 实例化一个线程锁
14 for i in range(50):
15     t = threading.Thread(target=run) # 实例化一个线程
16     t.start() # 启动线程
17     t_obj.append(t) # 将线程加入线程列表
18 
19 for j in t_obj: # 循环线程列表
20     j.join()
21 
22 print("----------all threads has finished...",threading.current_thread(),threading.active_count())
23 print("num:",num)

 

递归锁:

Rlock 递归锁,它相当于一个字典,记录了锁的门与锁的对应值,当开门的时候会根据对应来开锁.

 1 import threading  # 导入模块
 2 
 3 def run1():
 4     lock.acquire() # 加锁
 5     global num1
 6     num1 += 1
 7     lock.release() # 解锁
 8     return num1
 9 
10 def run2():
11     lock.acquire() # 加锁
12     global num2
13     num2 += 1
14     lock.release() # 解锁
15     return num2
16 
17 def run3():
18     lock.acquire() # 加锁
19     res = run1() # run1函数中也有锁操作
20     print("run1:",res)
21     res2 = run2() # run2函数中也有锁操作
22     print("run2:",res2)
23     lock.release() # 解锁
24 
25 lock = threading.RLock() # 实例化锁
26 num1 = 0
27 num2 = 0
28 t_obj = [] # 线程列表
29 for i in range(10):
30     t = threading.Thread(target=run3)
31     t.start()
32     t_obj.append(t)
33     while threading.active_count() != 1:
34         # print(threading.active_count()) # 打印当前运行的线程数
35         pass
36     else:
37         print("num1:%s, num2:%s" % (num1, num2))

信号量

 1 import  threading,time
 2 
 3 def run(n):
 4     semaphore.acquire()  # 加锁
 5     time.sleep(1)
 6     print("in run:",n)
 7     semaphore.release() # 解锁
 8 
 9 semaphore = threading.BoundedSemaphore(3) # 加锁的情况下,允许3个线程同时执行,不必等线程解锁后下个线程才工作,3线程并发
10 for i in range(20):
11     t  = threading.Thread(target=run,args=(i,))
12     t.start()