一、线程
1.线程
1)、什么是线程
线程是cpu调度的最小单位
线程是进程的必要组成单位
一个进程里至少含有一个线程
2)、主线程
程序开始运行的视乎,就产生了一个主线程来运行这个程序
3)、子线程
是由主线程开启的其他线程
4)、各线程之间的工作
异步的
数据共享的
5)、GIL Cpython全局解释器锁
Cpython解释器,在同一个进程中的多个线程,每次只能有一个线程可以获得执行CPU的权限。
这是由于Cpython的垃圾回收线程等原因导致
2.线程的开启
# 线程不能在外界的干扰下结束,而是等待程序的执行完毕才结束,主线程要等待子线程的结束而结束。
from threading import Thread,currentThread def t_func(): global n n -= 1 print(currentThread()) if __name__ == '__main__': n = 100 t_lst = [] for i in range(100): t = Thread(target=t_func) t.start() t_lst.append(t) print(t.ident,t.name,t.is_alive()) for t in t_lst:t.join() print(n)
3.守护线程
# 守护线程,会等待主线程执行完毕才结束,主线程会等待所有子线程结束而结束。
from threading import Thread,currentThread,active_count,enumerate import time def func1(): time.sleep(3) print('in func1') def func2(): while True: time.sleep(0.5) print('in func2') if __name__ == '__main__': Thread(target=func1).start() t = Thread(target=func2, daemon=True) # t.setDaemon(True) # t.daemon = True t.start() # print(enumerate()) # print(active_count()) # print(currentThread()) # print(t.getName()) # print(t.setName('zzz')) # print(t.getName()) print('主线程') # 守护线程:会等待主线程执行完毕而结束,主线程会等待所有子进程结束后才结束
4.锁
区别GIL和锁,GIL只是同进程中的不同线程只能有一个线程访问CPU,而互斥锁,是保障数据安全的一种机制,二者不冲突。
from threading import Lock,RLock,Thread # 数据不安全实例,由于global数据共享,导致两个线程可能仅计算完+8,还未写入,就被另一个线程抢到执行 # 权限被赋值为0 # def change_balance(n): # global balance # balance += n # balance -= n # # # def run_thread(n): # for i in range(150000): # change_balance(n) # # # balance = 0 # t1 = Thread(target=run_thread, args=(5,)) # t2 = Thread(target=run_thread, args=(8,)) # t1.start() # t2.start() # t1.join() # t2.join() # print(balance) # 加锁 保障数据安全 def change_balance(n): global balance balance += n balance -= n def run_thread(n): for i in range(150000): with lock:change_balance(n) balance = 0 lock = Lock() t1 = Thread(target=run_thread, args=(5,)) t2 = Thread(target=run_thread, args=(8,)) t1.start() t2.start() t1.join() t2.join() print(balance)
5.死锁和递归锁
互斥锁和递归锁的区别:
#互斥锁在同一个线程中连续acquire一次以上就会死锁
#递归锁在同一个线程中可以连续的acquire多次而不发生死锁
#普遍:递归锁可以代替互斥锁来解决死锁现象
#实际上:递归锁的解决死锁实际上是牺牲了时间和空间的
# 死锁从本质上来说是一种逻辑错误
# 递归锁没有从根本上解决死锁问题
递归锁画图描述:
from threading import Lock # 互斥锁 # lock = Lock() # lock.acquire() # print(123) # lock.release() from threading import RLock # 递归锁 # lock = RLock() # lock.acquire() # lock.acquire() # print(123) # lock.release() # 死锁 # 科学家吃面问题 # import time # from threading import Thread,Lock # # def eat1(name,fork_lock,noodle_lock): # fork_lock.acquire() # print('%s拿到叉子了'%name) # noodle_lock.acquire() # print('%s拿到面条了' % name) # print('%s吃面'%name) # noodle_lock.release() # fork_lock.release() # # def eat2(name,fork_lock,noodle_lock): # noodle_lock.acquire() # print('%s拿到面条了' % name) # time.sleep(1) # fork_lock.acquire() # print('%s拿到叉子了' % name) # print('%s吃面'%name) # fork_lock.release() # noodle_lock.release() # # fork_lock = Lock() # noodle_lock = Lock() # Thread(target=eat1,args=('alex',fork_lock,noodle_lock)).start() # Thread(target=eat2,args=('wusir',fork_lock,noodle_lock)).start() # Thread(target=eat1,args=('yuan',fork_lock,noodle_lock)).start() # Thread(target=eat2,args=('jin',fork_lock,noodle_lock)).start() # 递归锁解决死锁现象 # import time # from threading import Thread,RLock # # def eat1(name,fork_lock,noodle_lock): # fork_lock.acquire() # print('%s拿到叉子了'%name) # noodle_lock.acquire() # print('%s拿到面条了' % name) # print('%s吃面'%name) # noodle_lock.release() # fork_lock.release() # # def eat2(name,fork_lock,noodle_lock): # noodle_lock.acquire() # print('%s拿到面条了' % name) # time.sleep(1) # fork_lock.acquire() # print('%s拿到叉子了' % name) # print('%s吃面'%name) # fork_lock.release() # noodle_lock.release() # # noodle_lock = fork_lock = RLock() # Thread(target=eat1,args=('alex',fork_lock,noodle_lock)).start() # Thread(target=eat2,args=('wusir',fork_lock,noodle_lock)).start() # Thread(target=eat1,args=('yuan',fork_lock,noodle_lock)).start() # Thread(target=eat2,args=('jin',fork_lock,noodle_lock)).start() # import time # from threading import Thread,RLock # # def eat1(name,lock): # lock.acquire() # print('%s拿到叉子了'%name) # print('%s拿到面条了' % name) # print('%s吃面'%name) # lock.release() # # def eat2(name,lock): # lock.acquire() # print('%s拿到面条了' % name) # time.sleep(1) # print('%s拿到叉子了' % name) # print('%s吃面'%name) # lock.release() # # noodle_fork_lock = Lock() # Thread(target=eat1,args=('alex',noodle_fork_lock)).start() # Thread(target=eat2,args=('wusir',noodle_fork_lock)).start() # Thread(target=eat1,args=('yuan',noodle_fork_lock)).start() # Thread(target=eat2,args=('jin',noodle_fork_lock)).start() # 互斥锁和递归锁的区别 ***** # 互斥锁在同一个线程中连续acquire一次以上就会死锁 # 递归锁在同一个线程中可以连续的acquire多次而不发生死锁 # 普遍 :递归锁可以代替互斥锁来解决死锁现象 # 实际上 : 递归锁的解决死锁实际上是牺牲了时间和空间的 **** # 死锁从本质上来讲是一种逻辑错误 # 递归锁没有从根本上解决死锁问题
6.事件
event.isSet():返回event的状态值;
event.wait():如果 event.isSet()==False将阻塞线程;
event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;
event.clear():恢复event的状态值为False。
from threading import Thread,Event,currentThread import time,random def check_mysql(): print('