zoukankan      html  css  js  c++  java
  • (9)开启线程的互斥锁

    使用互斥锁

    from threading import Thread,Lock #从threading包内倒入Lock模块

    mutex = Lock() #定义锁
    x = 100
    def task():
    global x
    mutex.acquire() # 获得锁
    temp = x
    x = temp - 1
    mutex.release() # 释放锁
    if __name__ == '__main__':
    t_l = []
    for i in range(100):
    t = Thread(target=task)
    t_l.append(t)
    t.start()

    for t in t_l:
    t.join()

    print(x) #最终结果就是0

    了解知识:死锁和解决死锁的方法(递归锁) 信号量

    死锁实例

    import time
    from threading import Thread, Lock

    mutexA = Lock()
    mutexB = Lock()

    class Mythread(Thread):
    def run(self):
    self.f1()
    self.f2()

    def f1(self):
    mutexA.acquire()
    print('%s 拿到A锁' % self.name) #self.name是线程名
    mutexB.acquire()
    print('%s 拿到B锁' % self.name)
    mutexB.release()
    mutexA.release()

    def f2(self):
    mutexB.acquire()
    print('%s 拿到B锁' % self.name)
    time.sleep(1)
    mutexA.acquire()
    print('%s 拿到了A锁' % self.name)
    mutexA.release()
    mutexB.release()

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

    代码解读:

    开始执行函数,此时10个线程同时起来了,第一个线程在执行run,run里面执行两个函数f1和f2,线程1拿到了A锁,线程1又拿到了B锁,此时程序再往下走线程1释放了A锁和B锁,紧接着执行f2函数,此时线程1拿到了B锁,然后睡了1秒的同时,线程2起来了,线程2执行f1,此时线程2拿到了A锁,线程2想要拿B锁,由于线程是异步的,所以此时B锁在线程1的f2里睡着(1秒),此时线程1一秒过后想要拿A锁,但是这时候A锁在线程2里面等着释放(线程2还在执行f1,等着拿到B锁再执行释放A,B锁)所以这时候线程1在执行f2代码的时候由于A锁再线程2手里,得不到A锁代码就走不下去(无法执行后面的释放代码),线程2想要拿B锁,由于B锁在线程1手里(无法执行后面的释放代码),所以就形成了死锁递归锁,程序执行不下去

    解决死锁的办法(使用RLock递归锁)

    import time
    from threading import Thread, RLock #使用递归锁要倒入RLock模块

    obj = RLock() #实例化一个变量等于RLock
    mutexA = obj #obj赋值给变量
    mutexB = obj

    class Mythread(Thread):
    def run(self):
    self.f1()
    self.f2()

    def f1(self):
    mutexA.acquire()
    print('%s 拿到A锁' % self.name) #self.name是线程名
    mutexB.acquire()
    print('%s 拿到B锁' % self.name)
    mutexB.release()
    mutexA.release()

    def f2(self):
    mutexB.acquire()
    print('%s 拿到B锁' % self.name)
    time.sleep(1)
    mutexA.acquire()
    print('%s 拿到了A锁' % self.name)
    mutexA.release()
    mutexB.release()

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

    PS:RLock递归锁的特点就是可以连续的acquire(上锁)不需要release(释放),而通常的Lock不能连续acquire(上锁),必须release(释放)后才能再次acquire(上锁)

    信号量实例

    信号量是控制同一时刻并发执行的任务数(和线程池、进程池很相似)

    from threading import Thread,Semaphore,current_thread
    import time,random

    sm = Semaphore(5) #括号内就是设置并发执行的任务数

    def task():
    with sm: # with 这个关键词就是把acquire和release合并成一步,自动执行,不需要写代码了
    print('%s 正在上厕所' %current_thread().name)
    time.sleep(random.randint(1,4))

    if __name__ == '__main__':
    for i in range(20):
    t = Thread(target=task)
    t.start()

    PS:可以看到第一次最多同时执行了5个线程,然后是有几个线程优先结束,然后执行几个线程

  • 相关阅读:
    gitlab搭建
    java数组
    安裝nextcloud
    Spring的定时任务@Scheduled(cron = "0 0 1 * * *")
    java内存结构(下)
    java内存结构(上)
    多线程的三个特性
    @RequestBody用法
    SwaggerAPI注解详解(转载)
    在jpanel中添加jbutton并自由设置按钮大小和位置
  • 原文地址:https://www.cnblogs.com/shizhengquan/p/10270436.html
Copyright © 2011-2022 走看看