python之线程了解部分

一、死锁(了解)

  • 死锁产生的4个必要条件:
    • 互斥:一个资源同一时刻只允许一个线程进行访问
    • 占有未释放:一个线程占有资源,且没有释放资源
    • 不可抢占:一个已经占有资源的线程无法抢占到其他线程拥有的资源
    • 循环等待:两个或者两个以上的线程,本身拥有资源,不释放资源,并且同时尝试获得其他线程所持有的资源,这种资源的申请关系形成一个闭环的链条

  • 死锁的避免:关于死锁的避免,仁者见仁智者见智
    • 线程等待时(wait)给予一个默认的等待时间
    • 线程之间资源避免相互申请对方的资源,可以通过一些容器来控制并发,比如blockqueue,等等一些线 程安全的容器
    • 尽量避免线程在等待的同时申请资源
    • 死锁检测,一个线程在等待一段时间后还没有获得资源就放弃申请。对等待时间进行检测
from threading import Thread, Lock
import time

mutexA = Lock()
mutexB = Lock()

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

    def func1(self):
        mutexA.acquire()
        print('%s 抢到A锁' % self.name)  # 获取当前线程名
        mutexB.acquire()
        print('%s 抢到B锁' % self.name)
        mutexB.release()
        mutexA.release()

    def func2(self):
        mutexB.acquire()
        print('%s 抢到B锁' % self.name)
        time.sleep(2)
        mutexA.acquire()
        print('%s 抢到A锁' % self.name)  # 获取当前线程名
        mutexA.release()
        mutexB.release()

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

二、递归锁(了解)

  • 递归锁的特点
    • 可以被连续的acquire和release
    • 但是只能被第一个抢到这把锁执行上述操作
    • 它的内部有一个计数器
      • acquire一次计数加一
      • realse一次计数减一
    • 只要计数不为0 那么其他人都无法抢到该锁
"""
# 将上述的
mutexA = Lock()
mutexB = Lock()
# 换成
mutexA = mutexB = RLock()

三、信号量(了解)

  • 信号量在不同的阶段可能对应不同的技术点

  • 在并发编程中信号量指的是锁!!!

"""
如果我们将互斥锁比喻成一个厕所的话
那么信号量就相当于多个厕所
"""

Event事件(了解)

一些进程/线程需要等待另外一些进程/线程运行完毕之后才能运行,类似于发射信号一样

from threading import Thread, Event
import time

event = Event()  # 造了个红绿灯


def ligit():
    print('红灯亮了')
    time.sleep(2)
    print('绿地亮了')
    # 此时告诉等待绿灯的人可以走了
    event.set()

def car(name):
    print(F'{name}正在等红灯')
    event.wait()
    #执行完wait,车才能走
    print(F'绿灯了,{name}开车走了')

if __name__ == '__main__':
    t = Thread(target=ligit)
    t.start()

    for i in range(10):
        t = Thread(target=car, args=(F'{i+1}车',))
        t.start()

四、线程q(了解)

"""
同一个进程下多个线程数据是共享的
为什么先同一个进程下还会去使用队列呢
因为队列是
    管道 + 锁
所以用队列还是为了保证数据的安全
"""
import queue

# 我们现在使用的队列都是只能在本地测试使用

# 1 队列q  先进先出
# q = queue.Queue(3)
# q.put(1)
# q.get()
# q.get_nowait()
# q.get(timeout=3)
# q.full()
# q.empty()


# 后进先出q
# q = queue.LifoQueue(3)  # last in first out
# q.put(1)
# q.put(2)
# q.put(3)
# print(q.get())  # 3

# 优先级q   你可以给放入队列中的数据设置进出的优先级
q = queue.PriorityQueue(4)
q.put((10, '111'))
q.put((100, '222'))
q.put((0, '333'))
q.put((-5, '444'))
print(q.get())  # (-5, '444')
# put括号内放一个元祖  第一个放数字表示优先级
# 需要注意的是 数字越小优先级越高!!!
posted @ 2020-10-01 22:41  taotaozh  阅读(128)  评论(0编辑  收藏  举报