-
进程:是程序,资源集合,进程控制块组成,是最小的资源单位
- 特点:就对Python而言,可以实现真正的并行效果
- 缺点:进程切换很容易消耗cpu资源,进程之间的通信相对线程来说比较麻烦
-
线程:是进程中最小的执行单位。
- 特点无法利用多核,无法实现真正意义上是并行效果。
- 优点:对于IO密集型的操作可以很好利用IO阻塞的时间
开启多线程,操作同一个数据时需要加锁
import threading import time class MyThread(threading.Thread): def __init__(self): super(MyThread,self).__init__() def run(self): global x #获得锁 lock.acquire() for i in range(3): x = x +i time.sleep(2) print(x) #释放锁 lock.release() #创建锁lock = threading.RLock() t1 = [] for i in range(10): t = MyThread() t1.append(t) x = 0 for i in t1: i.start()
Lock重复获取会导致程序阻塞
def func(name): global x lock.acquire() print("%s线程开始"%name) temp = x time.sleep(0.2) x = temp +1 lock.acquire() # 在锁未释放的时候第二次获得锁,需要注意的是这里的锁指的是同一个锁对象 print("%s线程结束" % name) lock.release() lock.release() if __name__ == '__main__': lock = threading.Lock() m = time.time() x = 100 t = [] for i in range(10): s = threading.Thread(target=func,args=("thread%s"%i,)) s.start() t.append(s) for i in t: i.join() print(x) print(time.time()-m)
RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。这里以例1为例,如果使用RLock代替Lock,则不会发生死锁
def func(name): global x lock.acquire() print("%s线程开始"%name) temp = x time.sleep(0.2) x = temp +1 lock.acquire() #线程中前面的acquire还未被释放,即使在acquire也不会真的获取 print("%s线程结束" % name) lock.release() lock.release() if __name__ == '__main__': lock = threading.RLock() #由Rlock 替换Lock,避免死锁 m = time.time() x = 100 t = [] for i in range(10): s = threading.Thread(target=func,args=("thread%s"%i,)) s.start() t.append(s) for i in t: i.join() print(x) print(time.time()-m)