并发:逻辑上具备同时处理多个任务的能力。
并行:物理上在同一时刻执行多个并发任务。
举例:开个QQ,开了一个进程,开了微信,开了一个进程。在QQ这个进程里面,传输文字开一个线程、传输语音开了一个线程、弹出对话框又开了一个线程。
总结:开一个软件,相当于开了一个进程。在这个软件运行的过程里,多个工作同时运转,完成了QQ的运行,那么这个多个工作分别有多个线程。
线程和进程之间的区别:
1.多线程-几个基本概念的了解
进程在python中的使用,对模块threading进行操作,调用的这个三方库。可以通过help(threading)
了解其中的方法、变量使用情况。也可以使用dir(threading)
查看目录结构。
- 多线程使用的几个概念:
r_synchronization=threading.Lock()
#同步锁
r_synchronization.acquire()
#调用变量r_synchronization
进行上锁,用于业务开始之前先对操作进行上锁操作
r_synchronization.release()
#调用变量r_synchronization
解锁,用于业务结束之前对操作进行解锁操作
#递归锁,与同步锁的操作方法保持一致。
r_recursion.acquire() #上锁
r_recursion.release() #解锁
r_recursion=threading.RLock #递归锁
current_thread_n = threading.current_thread() # 返回当前线程
current_thread_num = threading.active_count()
# 返回正在运行的线程数量
run_thread_len = len(threading.enumerate())
# 返回正在运行的线程数量
run_thread_list = threading.enumerate()
# 返回当前运行线程的列表
t1=threading.Thread(target=dance)
#创建两个子线程,参数传递为函数名
t1.setDaemon(True)
# 设置守护进程,守护进程:主线程结束时自动退出子线程。
t1.start()
# 启动子线程
t1.join()
# 等待进程结束exit()`# 主线程退出,t1子线程设置了守护进程,会自动退出。其他子线程会继续执行。
2.实例-几个概念的使用
import threading,time
def dance():
for i in range(5):
print('我在唱歌')
time.sleep(1)
def wu():
for i in range(5):
print('我在跳舞')
time.sleep(0.5)
if __name__=='__main__':
#创建两个子线程,参数传递为函数名
t1 = threading.Thread(target=dance)
t2 = threading.Thread(target=wu)
#设置守护进程,守护进程:主线程结束时自动退出子线程。
t1.setDaemon(True)
#启动子线程
t1.start()
t2.start()
#等待进程结束
t1.join()
t2.join()
print('over')
#主线程退出,t1子线程设置了守护进程,会自动退出。t2子线程会继续执行。
exit()
current_thread_n= threading.current_thread() # 返回当前线程
# 返回正在运行的线程数量
current_thread_num=threading.active_count()
run_thread_len=len(threading.enumerate())
run_thread_list=threading.enumerate() # 返回当前运行线程的列表
3.不安全的并发-同步锁
- 场景:2件事情都需要操作一个变量,几乎同时发生,这个时候,显然并发操作是不安全的。
- 解决方案:上锁(有2种方法:threading.Lock()-同步锁、threading.RLock()-递归锁)
import threading,time
account_account =500 #银行账号500元
r =threading.Lock() #一把锁,同步锁
#操作一个银行账号
def foo(num):
r.acquire() #上锁
global account_account #申明全局变量的引用
balance =account_account #通过接口调用到账号
time.sleep(1)
balance = balance+num
account_account =balance #计算结束,要将结果存回数据库或者通过接口返回新的余额。
r.release() #解锁
t1 =threading.Thread(target=foo,args=(10000,)) #收入
t2 =threading.Thread(target=foo,args=(-200,))#把钱发出去
#启动线程
t1.start()
t2.start()
t1.join()
t2.join()
print('最终余额:',account_account)
4.不安全的并发-递归锁
#递归锁
import time,threading
# lockA =threading.Lock() #面试人员的锁
# lockB = threading.Lock() #小红的锁
r =threading.RLock() #递归锁
def foo1():
r.acquire()#上锁
print('请解释什么是死锁')
time.sleep(1)
r.acquire() #上锁
print('发offer')
#解锁
r.release()
r.release()
def foo2():
r.acquire()
print('请给我offer')
time.sleep(1)
r.acquire()
print('向面试官解释什么是死锁')
time.sleep(1)
r.release()
r.release()
t1 =threading.Thread(target=foo1) #收入
t2 =threading.Thread(target=foo2)#把钱发出去
t1.start()
t2.start()