python线程

  • 进程:是程序,资源集合,进程控制块组成,是最小的资源单位
    • 特点:就对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)

 

你可能感兴趣的:(python线程)