首页 > 其他 > 详细

并发编程其它

时间:2021-02-25 15:08:57      阅读:28      评论:0      收藏:0      [点我收藏+]

内容概要

  一、死锁与递归锁(了解)

  二、信号量(了解)

  三、Event事件(了解)

  四、其它线程q(了解)

  五、进程池与线程池

  六、协程

  七、协程实现TCP并发(了解)

 

1、死锁与递归锁

  虽然互斥锁的语法看起来很简单,就是一acquire对应一release,但是在多并发情况下,使用多把互斥锁容易造成死锁现象

  死锁现象例子

from threading import Thread,Lock
import time

# metuxA = Lock()
# metuxB = Lock()  # 锁A和锁B是两把不同的锁

class MyThread(Thread):
    def run(self):
        self.func1()
        self.func2()

    def func1(self):
        metuxA.acquire()
        print({}抢到了锁A.format(self.name))
        metuxB.acquire()
        print({}抢到了锁B.format(self.name))
        metuxA.release()
        metuxB.release()

    def func2(self):
        metuxB.acquire()
        print({}抢到了锁B.format(self.name))
        time.sleep(2)
        metuxA.acquire()
        print({}抢到了锁A.format(self.name))
        metuxA.release()
        metuxB.release()

if __name__ == __main__:
    for i in range(10):
        t = MyThread()
        t.start()

  执行这个程序,会发生线程1抢了锁A,想抢锁B;但是线程2已经抢了锁B,它又想抢锁A,两个线程彼此卡住。

 

  要想解决死锁现象,可以将所有不同的锁设置为同一把递归锁

  Rlock是递归锁

from threading import Thread,RLock
import time

metuxA = metuxB = RLock()
# 递归锁的特点:
‘‘‘
递归锁可以被连续acquire和release,当每次acquire时,锁内部的计数器自动加一;
当每次release时,锁内部的计数器自动减一。当计数为0时,锁才能真正被释放,其它线程才能枪锁
‘‘‘

class MyThread(Thread):
    def run(self):
        self.func1()
        self.func2()

    def func1(self):
        metuxA.acquire()
        print({}抢到了锁A.format(self.name))
        metuxB.acquire()
        print({}抢到了锁B.format(self.name))
        metuxA.release()
        metuxB.release()

    def func2(self):
        metuxB.acquire()
        print({}抢到了锁B.format(self.name))
        time.sleep(2)
        metuxA.acquire()
        print({}抢到了锁A.format(self.name))
        metuxA.release()
        metuxB.release()

if __name__ == __main__:
    for i in range(10):
        t = MyThread()
        t.start()

 

2、信号量

  如果说Lock是多个人抢一把锁,那么信号量就是多个人可以抢多把锁

  Semaphore是信号量

from threading import Thread,Semaphore
import time
import random

sm = Semaphore(5)

def work(i):
    sm.acquire()
    print(伞兵{}号准备就绪.format(i))
    time.sleep(random.randrange(2,5))
    print(伞兵{}号落地成盒.format(i))
    sm.release()

if __name__ == __main__:
    for i in range(1,21):
        t = Thread(target=work,args=(i,))
        t.start()

 

3、Event事件

  一般来说,主线程会等待所有非守护线程结束之后才结束

  Event事件用于实现子线程之间彼此等待,或者子线程等待主线程

from threading import Thread, Event
import time

event = Event()

def traffic_light():
    print(红灯亮了)
    print(event.is_set())  # 打印_flag当前的值
    time.sleep(8)
    print(绿灯亮了)
    event.set()  # 设置_flag为True
    print(event.is_set())  # 打印_flag当前的值

def car(i):
    print({}车在等待.format(i))
    event.wait()  # 执行到这里,判断_flag的值,False时阻塞;True时同行
    print({}车开了.format(i))

if __name__ == __main__:
    t2 = Thread(target=traffic_light)
    t2.start()
    for i in range(1,10):
        t = Thread(target=car,args=(i,))
        t.start()

event.clear()  # 设置_flag为False

 

4、其它线程q

# 堆栈队列
import queue

# 堆栈队列:后进先出
q = queue.LifoQueue(4)

q.put(11)
q.put(22)
q.put(33)
q.put(44)
print(q.get())
print(q.get())
print(q.get())
print(q.get())

# 优先级队列
q = queue.PriorityQueue(4)

q.put((22,wwww))
q.put((-2,eeee))
q.put((222,qqqq))
print(q.get())
print(q.get())
print(q.get())
‘‘‘ 优先级队列put方法要传入一个元组,该元组第一个值表示数据提取的优先级,可以为负数,且数字越小,优先级越高‘‘‘

 

5、线程池与进程池

 

并发编程其它

原文:https://www.cnblogs.com/laijianwei/p/14446303.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!