1. GIL:全局解释锁:无论开启多少个线程,同一时刻只允许执行一个线程运行(解释器级别,保护数据)
    :两种状态,锁定和未锁定,仅支持两个函数,获得锁和释放锁
      多线程抢夺锁时,当某个线程获得锁了,其他的锁都会被阻塞,直到这个线程释放锁后,其他线程才可以再抢夺锁,注意线程抢夺锁是没有顺序的
    同步锁Lock,与GIL不同,它是用户层面上的,由用户自定义
  1. import threading
  2. import time
  3.  
  4. def sub():
  5. global num
  6.  
  7. # 加上一个锁,使得本来并发的变成串行,用来保护自己的数据不被其他的线程拿到
  8. lock.acquire() #获得锁
  9. temp = num
  10. time.sleep(0.01) #当阻碍时间较长时,其他的线程可能也会拿到这个数据
  11. num = temp - 1
  12. lock.release() #释放锁
  13.  
  14. num = 100
  15.  
  16. l = []
  17. lock = threading.Lock() #声明一个锁
  18.  
  19. for i in range(100):
  20. t = threading.Thread(target=sub)
  21. t.start()
  22. l.append(t)
  23. for t in l:
  24. t.join()
  25. print(num)
  1. 死锁:当存在多线程时,双方都在等对方释放锁,产生死锁,当无外力作用时,程序将无法推进下去
    递归锁RLock内部维护着一个counter,每次acquire都会使得counter + 1 ,每release一次counter - 1
      counter大于0时,只能有一个线程可以获得这个锁,只有等于0时,其他线程才能获得这个锁
  1. import threading
  2. import time
  3.  
  4. class MyThread(threading.Thread):
  5. def action1(self):
  6. t1.acquire()
  7. print(self.name,"got t1",time.ctime)
  8. time.sleep(2)
  9.  
  10. t2.acquire()
  11. print(self.name,"got t2",time.ctime)
  12. time.sleep(2)
  13.  
  14. t2.release()
  15. t1.release()
  16.  
  17. def action2(self):
  18. t2.acquire()
  19. print(self.name, "got t2", time.ctime)
  20. time.sleep(2)
  21.  
  22. t1.acquire()
  23. print(self.name, "got t1", time.ctime)
  24. time.sleep(2)
  25.  
  26. t1.release()
  27. t2.release()
  28.  
  29. def run(self):
  30. self.action1()
  31. self.action2()
  32.  
  33. if __name__ == '__main__':
  34. t1 = threading.Lock()
  35. t2 = threading.Lock()
  36.  
  37. L = []
  38.  
  39. for i in range(5):
  40. t = MyThread()
  41. t.start()
  42. L.append(t)
  43.  
  44. for t in L:
  45. t.join()
  46.  
  47. print("end...")

解决产生死锁:使用递归锁,t1,t2的锁声明改为 threading.RLock()

同步条件:Event

  1. #创建Event对象
    event = threading.Event
  2.  
  3. 3个方法
    #a client thread wait for the flag to be set
    event.wait()
  4.  
  5. #a server thread can set or reset it
    event.set()
    event.clear()
    使用规则
    if the flag is set , the wait method doesn't do anything
    if the flag is cleared ,the wait block until it becomes set again
    any number of threads may wait for the same event
  1. import threading,time
  2. class Boss(threading.Thread):
  3. def run(self):
  4. print("BOSS:everybody works overtime tonight。")
  5. print(event.isSet())
  6. event.set()
  7. time.sleep(5)
  8. print("BOSS:can leave work。")
  9. print(event.isSet())
  10. event.set()
  11. class Worker(threading.Thread):
  12. def run(self):
  13. event.wait() #当Event没有set时,wait方法被调用,阻塞,当Event被set后,这个wait方法就相当于pass
  14. print("Worker:ah……life is bitter!")
  15. time.sleep(1)
  16. event.clear()
  17. event.wait()
  18. print("Worker:OhYeah!")
  19. if __name__=="__main__":
  20. event=threading.Event()
  21. threads=[]
  22. for i in range(5):
  23. threads.append(Worker())
  24. threads.append(Boss())
  25. for t in threads:
  26. t.start()
  27. for t in threads:
  28. t.join()

信号量:Semaphore

  用来控制线程并发数,当同时并发的线程达到指定的最大数时,其他线程将会被阻塞

  BoundedSemaphore或Semaphore内置一个计数器,当acquire()时 -1,当release()时 +1,

  计数器不能小于0,当计数器等于0时,acquire()将线程阻塞同步至锁定状态,直到有线程release()释放

  BoundedSemaphore和Semaphore的区别:BoundedSemaphore在调用release()检测计数器是否超过设定值,达到抛出一个异常

  1. import threading,time
  2. class myThread(threading.Thread):
  3. def run(self):
  4. if semaphore.acquire():
  5. print(self.name)
  6. time.sleep(5)
  7. semaphore.release()
  8. if __name__=="__main__":
  9. semaphore=threading.Semaphore(5) #设置可以同时有几个线程并发
  10. thrs=[]
  11. for i in range(100):
  12. thrs.append(myThread())
  13. for t in thrs:
  14. t.start()

锁,Event,semaphore的更多相关文章

  1. 【分布式锁】07-Zookeeper实现分布式锁:Semaphore、读写锁实现原理

    前言 前面已经讲解了Zookeeper可重入锁的实现原理,自己对分布式锁也有了更深的认知. 我在公众号中发了一个疑问,相比于Redis来说,Zookeeper的实现方式要更好一些,即便Redis作者实 ...

  2. Day12- Python基础12 线程、GIL、Lock锁、RLock锁、Semaphore锁、同步条件event

    http://www.cnblogs.com/yuanchenqi/articles/6248025.html  博客地址 本节内容: 1:进程和线程的说明 2:线程的两种调用方式 3:threadi ...

  3. 并发编程~~~多线程~~~守护线程, 互斥锁, 死锁现象与递归锁, 信号量 (Semaphore), GIL全局解释器锁

    一 守护线程 from threading import Thread import time def foo(): print(123) time.sleep(1) print('end123') ...

  4. 带你看看Java的锁(二)-Semaphore

    前言 简介 Semaphore 中文称信号量,它和ReentrantLock 有所区别,ReentrantLock是排他的,也就是只能允许一个线程拥有资源,Semaphore是共享的,它允许多个线程同 ...

  5. 同步锁 死锁与递归锁 信号量 线程queue event事件

    二个需要注意的点: 1 线程抢的是GIL锁,GIL锁相当于执行权限,拿到执行权限后才能拿到互斥锁Lock,其他线程也可以抢到GIL,但如果发现Lock任然没有被释放则阻塞,即便是拿到执行权限GIL也要 ...

  6. Python之网路编程之死锁,递归锁,信号量,Event事件,线程Queue

    一.死锁现象与递归锁 进程也是有死锁的 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用, 它们都将无法推进下去.此时称系统处于死锁状态或系统 ...

  7. Python 中Semaphore 信号量对象、Event事件、Condition

    Semaphore 信号量对象 信号量是一个更高级的锁机制.信号量内部有一个计数器而不像锁对象内部有锁标识,而且只有当占用信号量的线程数超过信号量时线程才阻塞.这允许了多个线程可以同时访问相同的代码区 ...

  8. python基础-12 多线程queue 线程交互event 线程锁 自定义线程池 进程 进程锁 进程池 进程交互数据资源共享

    Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CP ...

  9. python多线程锁lock/Rlock/BoundedSemaphore/Condition/Event

    import time import threading lock = threading.RLock() n = 10 def task(arg): # 加锁,此区域的代码同一时刻只能有一个线程执行 ...

  10. 34、锁问题与线程queue

    上一篇随笔我们学了全局解释器锁,前面也学了互斥锁,今天学习一些与锁相关的点,例如递归锁,信号量,Event,还会学习我们已经很熟悉的队列,不过这次的队列是作为一个模块出现的. 一.同步锁 1.join ...

随机推荐

  1. Oracle数据库备份还原

    导出备份的命令: 开始->运行->cmd->exp username/password@tns_name file=d:\backup.dmp 导入备份的命令: 开始->运行- ...

  2. php中用生成的公钥、私钥进行加密解密

    $private_key = '-----BEGIN RSA PRIVATE KEY-----MIICXQIBAAKBgQDpoODVtnSztGyb//p+g/Ob36jb3jzWzS2qovOjp ...

  3. linux下插入U盘自动挂载后,用C获取其挂载点(cat /proc/mounts)

    现在已经能够通过libudev获取U盘插入时它的节点名(通过函数udev_device_get_devnode()),是/dev/sdb1 我现在的做法是读取/proc/mounts文件,找到有/de ...

  4. htonl(),htons(),ntohl(),ntons()--大小端模式转换函数

    不同机器内部对变量的字节存储顺序不同,有的采用大端模式(big-endian),有的采用小端模式(little-endian). 大端模式是指高字节数据存放在低地址处,低字节数据放在高地址处. 小端模 ...

  5. SSH port forwarding: bind: Cannot assign requested address

    https://www.electricmonk.nl/log/2014/09/24/ssh-port-forwarding-bind-cannot-assign-requested-address/

  6. Django学习之Cookie和Session

    一.Cookie 1.Cookie的由来 2.什么是Cookie 3.Cookie的原理 4.查看Cookie 二.Django中操作Cookie 1.获取Cookie 2.设置Cookie 3.删除 ...

  7. 【MAC】 命令行解压缩 rar 文件

    使用Mac解压rar文件很简单,总共分2步.step1:安装解压工具,step2:解压 1.使用Homebrew安装unrar brew install unrar 2.cd到rar文件的目录下,然后 ...

  8. Vue知识整理13:表单输入绑定(v-model)

    text:将输入框等表单,通过data变量实现数据绑定. textbox:数据绑定 3.checkbox和redio组件: 注意:data数据变量中,checkbox有可能会有多个结果,所以用数组: ...

  9. nacos 发布配置

    server 保留 2 份配置文件,一份在 mysql,一份在本地磁盘,同时在内存中缓存配置文件的 md5 值.当客户端获取配置时,server 直接返回本地磁盘文件,使用的是 sendFile ap ...

  10. Binary-to-text ecoding:

    binary to Text ecoding是指将二进制数据转换成可打印的符号 如果传输channel 不允许二进制数据(如email) 一般使用Base64 ASCII 标准使用128位来表示字母数 ...