一、并发与并行的区别
并发:交替做不同事的能力
并行:同时做不同事的能力行话解释:
并发:不同代码块交替执行的性能
并行:不同代码块同时执行的性能并发就是指代码逻辑上可以并行,有并行的潜力,但是不一定当前是真的以物理并行的方式运行
并发指的是代码的性质,并行指的是物理运行状态
二、线程与进程
什么是线程
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务
什么是进程
进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程
线程与进程的区别
- Threads share the address space of the process that created it; processes have their own address space.
- Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.
- Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes.
- New threads are easily created; new processes require duplication of the parent process.
- Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes.
- Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process does not affect child processes.
三、Python中的GIL
四、threading模块
import threading from time import ctime,sleep import time def music(func): for i in range(2): print ("Begin listening to %s. %s" %(func,ctime())) sleep(4) print("end listening %s"%ctime()) def move(func): for i in range(2): print ("Begin watching at the %s! %s" %(func,ctime())) sleep(5) print('end watching %s'%ctime()) threads = [] t1 = threading.Thread(target=music,args=('七里香',)) threads.append(t1) t2 = threading.Thread(target=move,args=('阿甘正传',)) threads.append(t2) if __name__ == '__main__': for t in threads: # t.setDaemon(True) t.start() # t.join() # t1.join() t2.join()########考虑这三种join位置下的结果? print ("all over %s" %ctime())
五、同步锁(Lock)
import time import threading def addNum(): global num #在每个线程中都获取这个全局变量 # num-=1 temp=num # print('--get num:',num ) time.sleep(0.1) num =temp-1 #对此公共变量进行-1操作 num = 100 #设定一个共享变量 thread_list = [] for i in range(100): t = threading.Thread(target=addNum) t.start() thread_list.append(t) for t in thread_list: #等待所有线程执行完毕 t.join() print('final num:', num )
程序运行结果不是 0
我们可以用加锁进行解决
import time import threading def addNum(): global num #在每个线程中都获取这个全局变量 # num-=1
# print('ok')
lock.acquire() temp=num time.sleep(0.1) num =temp-1 #对此公共变量进行-1操作 lock.release() num = 100 #设定一个共享变量 thread_list = [] lock=threading.Lock() for i in range(100): t = threading.Thread(target=addNum) t.start() thread_list.append(t) for t in thread_list: #等待所有线程执行完毕 t.join() print('final num:', num )
锁只锁在 lock.acquire() 与 lock.release() 之间的部分,这里面就相当于串行,也就是其他部分仍可以并发
同步锁与GIL的关系?
GIL是全局锁,保证在同一时刻只有一个线程在CPython解释器中执行,但这个线程可以随时被线程调度器(自己瞎编的)打断,就是说敏感数据无法保证在一个线程处理完后才能被下一个线程处理。
这时便需要同步锁,也就是我们的用户级互斥,通过加锁,可以保证敏感数据在只有被处理完毕后才能被下一个线程进行处理。