关于 Python 线程详述(2)

在这里不详细多说,关于GIL全局性解释器锁的详细信息,有兴趣可以参考:https://www.cnblogs.com/cjaaron/p/9166538.html

我们最重要的是需要理解,Python多线程适合IO密集型操作,但在计算密集型操作中,多线程甚至没有单线程快。

再来讲互斥锁(也就是线程锁)

  当多个线程同时修改一个数据的时候,可能会发生无法预估的错误,所以这时候要上锁。在这里叫做互斥锁。

def run():
    lock.acquire() # 获取锁
    global num
    num += 1
    lock.release() # 释放锁
    time.sleep(1)

if __name__ == "__main__":

lock = threading.Lock() # 生成锁的实例
    num = 0
    obj = []
    start = time.time()
    for i in range(1000):
        t= threading.Thread(target=run)
        t.start()
        obj.append(t)
    for j in obj:
        j.join()
    end = time.time()
    cost = end - start
    print("cost time:",cost)

print("num:",num)

递归锁

互斥锁之间可以嵌套,但是没有理清逻辑容易造成死锁,无法解开。这里使用递归锁,实现多层上锁和多层解锁

def run1():
    print("grab the first part data")
    lock.acquire()
    global num
    num += 1
    lock.release()
    return num

def run2():
    print("grab the second part data")
    lock.acquire()
    global num2
    num2 += 1
    lock.release()
    return num2

def run3():
    lock.acquire()
    res = run1()
    print('--------between run1 and run2-----')
    res2 = run2()
    lock.release()
    print(res, res2)

if __name__ == '__main__':

num, num2 = 0, 0
    lock = threading.RLock()  # 递归锁,设锁和解锁必须是成对的
    for i in range(10):
        t = threading.Thread(target=run3)
        t.start()

while threading.active_count() != 1:
    print(threading.active_count())
else:
    print('----all threads done---')
    print(num, num2)

需要注意的是:上锁和解锁必须是成对的。

信号量

信号量其实也是一种锁,用于限制线程的并发量,即同一时间只允许几个线程运行。

def run(n):
    semaphore.acquire()
    time.sleep(1)
    print("run the thread: {0}\n".format(n))
    semaphore.release()

if __name__ == '__main__':

semaphore = threading.BoundedSemaphore(5)  # 最多允许5个线程同时运行
    for i in range(20):
        t = threading.Thread(target=run, args=(i+1,))
        t.start()

while threading.active_count() != 1:
    pass  # print threading.active_count()
else:
    print('----all threads done---')

Timer

创建一个有延迟的线程。


def hello():
    print("hello, world")
 
t = Timer(30.0, hello)
t.start()  #  30秒后执行此线程

Event

threading.Event()用来实现两个或多个线程之间的交互

有四个方法:

    set() 设置标志位   

    clear()清空标志位   

    wait()如果已经设置标志位不会阻塞,如果没有设置标志位则产生阻塞   

    isSet() 判定是否设置了标志位。

接下来是一个车等红绿灯的例子,车是停还是行需要根据红绿灯来判定。将实例化若干个车(线程)和一个红绿灯(线程),来实现线程间交互

import threading
import time
import random

def light():
    "红绿灯"
    while True:
        count = 1
        event.set() # 标志位设定了,wait就不阻塞 #绿灯状态
        while True:
            if count == 1:
                print('\033[42;1m--green light on---\033[0m')
                time.sleep(10)
                count = 2
            elif count == 2:
                print('\033[43;1m--yellow light on---\033[0m')
                time.sleep(2)
                count = 3
            elif count == 3:
                event.clear() # 标志位被清空,wait()阻塞
                print('\033[41;1m--red light on---\033[0m')
                time.sleep(10)
                break

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/d543f07ad69e5d46f1b16ed0b5f37e1f.html