1. 1.互斥锁:
    原理:将并行变成串行
    精髓:局部串行,只针对共享数据修改
    保护不同的数据就应该用不用的锁
  1. from threading import Thread, Lock
  2. import time
  3.  
  4. n = 100
  5.  
  6. def task():
  7. global n
  8. mutex.acquire() # 效率低了 但是数据安全了
  9. temp = n
  10. time.sleep(0.1) # 100个线程 都拿到了100 所以就是 100个线程100-1
  11. n = temp - 1
  12. mutex.release()
  13.  
  14. if __name__ == '__main__':
  15. mutex = Lock()
  16. t_l = []
  17. for i in range(100):
  18. t = Thread(target=task)
  19. t_l.append(t)
  20. t.start()
  21.  
  22. for t in t_l:
  23. t.join()
  24.  
  25. print('主', n)
  26. """
  27. 主 99 原因: 100个线程 都拿到了100 所以就是 100个线程100-1 数据不安全 效率高但是不安全
  28. 要将并行改为串行
  29. """
  30. """
  31. 主 0 原因:效率低了 但是数据安全了
  32. """
  1. 2.GIL: global interpreter lock
    python3 test.py
    ps aux | grep test # linux
    tasklist | findstr python # windows python.exe
  2.  
  3. 运行python 会有几步:
    1.会有一个进程,进程内存空间 python解释器的代码先加载到内存空间
    2.test.py 内容加载到内存
    3.解释执行;代码交给了python解释器
    线程干活指向了python代码 python代码当作参数传给了解释器
    线程拿到解释器的代码,拿着python代码当作参数,执行
    垃圾回收线程运行解释器的代码
    垃圾回收线程和某一个线程冲突了,数据不安全,

  1. 开多个进程,GIL就没影响了, cpython解释器垃圾回收线程定期启动一个
    GIL:互斥锁,保证数据的安全 CPython解释器,同一时间只有一个线程运行
    GIL.acquire() 这样垃圾线程和线程就不会冲突了,这样回收机制就变得安全了
    GIL.release()
    python解释器,多线程有GIL存在,保证了一个进程下面多个线程的执行是一个一个执行的
  2.  
  3. GIL与自动的锁的工作原理:

  1. 总结:
    1.GIL 一个进程内的多个线程同一时间只能运行一个线程,垃圾回收线程是安全的
    2.针对不同的数据,就应该加不同的锁,解释器级别的GIL锁,只能保护解释器级别的数据,
    不能保护自己的数据,针对自己的共享数据还要加锁;
  2.  
  3. 线程首先抢的是;GIL锁,之后才是mutex
    官网:
    结论:在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势
  4.  
  5. GIL的存在:同一时刻,只能有一个线程在运行
    多核,多进程,但进程开销大,多线程,又不能用多核 ?
  6.  
  7. cpu干计算的,多个cpu
    1.如果是干计算的操作,多核省时间
    2.如果干IO阻塞型操作,多核没用
  8.  
  9. 程序运行:都会干计算和IO操作
  10.  
  11. 四个任务:
    1.1个核:开多线程 ,因为多进程能用上多核
    2.多核:
    计算密集型:用多进程,用多核,eg:金融行业的,计算比较多,虽然多进程开销大,但多核,保证了计算快
    IO密集型:用多线程,同一时间只能用一个核,1个核一个进程,多线程就在一个核上来回切和四个核来回切是一样的
  12.  
  13. 现在写的软件:
    网络打交道,网络的IO
    IO密集型,用多线程
  1. """
  2. 计算密集型应该用: 多进程 效率高
  3. """
  4. from multiprocessing import Process
  5. from threading import Thread
  6. import os,time
  7.  
  8. def work():
  9. res=0
  10. for i in range(100000000):
  11. res*=i
  12.  
  13. if __name__ == '__main__':
  14. l=[]
  15. print(os.cpu_count()) #本机为8核
  16. start=time.time()
  17. for i in range(8):
  18. # p=Process(target=work) #耗时8s多
  19. p=Thread(target=work) #耗时37s多
  20. l.append(p)
  21. p.start()
  22. for p in l:
  23. p.join()
  24. stop=time.time()
  25. print('run time is %s' %(stop-start))
  26.  
  27. """
  28. IO密集型:多线程 效率高
  29. """
  30. from multiprocessing import Process
  31. from threading import Thread
  32. import threading
  33. import os,time
  34. def work():
  35. time.sleep(2)
  36. print('===>')
  37.  
  38. if __name__ == '__main__':
  39. l=[]
  40. print(os.cpu_count()) #本机为8核
  41. start=time.time()
  42. for i in range(400):
  43. # p=Process(target=work) #耗时8s多,大部分时间耗费在创建进程上
  44. p=Thread(target=work) #耗时2s多
  45. l.append(p)
  46. p.start()
  47. for p in l:
  48. p.join()
  49. stop=time.time()
  50. print('run time is %s' %(stop-start))
  1. 3.死锁:
    你拿着我的锁,我拿着你的锁
  2.  
  3. 互斥锁:Lock()
    互斥锁只能acquire一次
  4.  
  5. 递归锁:RLock()
    可以连续acquire多次,每acquire一次计数器+1
    只有计数为0时,才能被抢到acquire
  1. from threading import Thread,Lock
  2. import time
  3.  
  4. mutexA=Lock()
  5. mutexB=Lock()
  6.  
  7. class MyThread(Thread):
  8. def run(self):
  9. self.f1()
  10. self.f2()
  11.  
  12. def f1(self):
  13. mutexA.acquire()
  14. print('%s 拿到了A锁' %self.name)
  15.  
  16. mutexB.acquire()
  17. print('%s 拿到了B锁' %self.name)
  18. mutexB.release()
  19.  
  20. mutexA.release()
  21.  
  22. def f2(self):
  23. mutexB.acquire()
  24. print('%s 拿到了B锁' % self.name)
  25. time.sleep(0.1)
  26.  
  27. mutexA.acquire()
  28. print('%s 拿到了A锁' % self.name)
  29. mutexA.release()
  30.  
  31. mutexB.release()
  32.  
  33. if __name__ == '__main__':
  34. for i in range(10):
  35. t=MyThread()
  36. t.start()
  37. """
  38. Thread-1 拿到了A锁 # 死锁了 卡住了
  39. Thread-1 拿到了B锁
  40. Thread-1 拿到了B锁
  41. Thread-2 拿到了A锁
  42. """
  1. # 互斥锁只能acquire一次
  2. # from threading import Thread,Lock
  3. #
  4. # mutexA=Lock()
  5. #
  6. # mutexA.acquire()
  7. # mutexA.release()
  8.  
  9. # 递归锁:可以连续acquire多次,每acquire一次计数器+1,只有计数为0时,才能被抢到acquire
  10. from threading import Thread,RLock
  11. import time
  12.  
  13. mutexB=mutexA=RLock()
  14.  
  15. class MyThread(Thread):
  16. def run(self):
  17. self.f1()
  18. self.f2()
  19.  
  20. def f1(self):
  21. mutexA.acquire()
  22. print('%s 拿到了A锁' %self.name)
  23.  
  24. mutexB.acquire()
  25. print('%s 拿到了B锁' %self.name)
  26. mutexB.release()
  27.  
  28. mutexA.release()
  29.  
  30. def f2(self):
  31. mutexB.acquire()
  32. print('%s 拿到了B锁' % self.name)
  33. time.sleep(2)
  34.  
  35. mutexA.acquire()
  36. print('%s 拿到了A锁' % self.name)
  37. mutexA.release()
  38.  
  39. mutexB.release()
  40.  
  41. if __name__ == '__main__':
  42. for i in range(10):
  43. t=MyThread()
  44. t.start()
  45. """
  46. Thread-1 拿到了A锁 # 解决了 死锁
  47. Thread-1 拿到了B锁
  48. Thread-1 拿到了B锁
  49. Thread-1 拿到了A锁
  50. Thread-2 拿到了A锁
  51. Thread-2 拿到了B锁
  52. Thread-2 拿到了B锁
  53. Thread-2 拿到了A锁
  54. Thread-4 拿到了A锁
  55. Thread-4 拿到了B锁
  56. Thread-5 拿到了A锁
  57. Thread-5 拿到了B锁
  58. Thread-5 拿到了B锁
  59. Thread-5 拿到了A锁
  60. Thread-7 拿到了A锁
  61. Thread-7 拿到了B锁
  62. Thread-7 拿到了B锁
  63. Thread-7 拿到了A锁
  64. Thread-9 拿到了A锁
  65. Thread-9 拿到了B锁
  66. Thread-9 拿到了B锁
  67. Thread-9 拿到了A锁
  68. Thread-3 拿到了A锁
  69. Thread-3 拿到了B锁
  70. Thread-3 拿到了B锁
  71. Thread-3 拿到了A锁
  72. Thread-6 拿到了A锁
  73. Thread-6 拿到了B锁
  74. Thread-6 拿到了B锁
  75. Thread-6 拿到了A锁
  76. Thread-10 拿到了A锁
  77. Thread-10 拿到了B锁
  78. Thread-10 拿到了B锁
  79. Thread-10 拿到了A锁
  80. Thread-8 拿到了A锁
  81. Thread-8 拿到了B锁
  82. Thread-8 拿到了B锁
  83. Thread-8 拿到了A锁
  84. Thread-4 拿到了B锁
  85. Thread-4 拿到了A锁
  86. """
  1. 4.信号量
      信号量也是一把锁,可以指定信号量为5,对比互斥锁同一时间只能有一个任务抢到锁去执行,
       信号量同一时间可以有5个任务拿到锁去执行
      信号量:同一时间有多个线程在进行
  1. from threading import Thread,Semaphore,currentThread
  2. import time,random
  3.  
  4. sm=Semaphore(1)
  5.  
  6. def task():
  7. # sm.acquire()
  8. # print('%s in' %currentThread().getName())
  9. # sm.release()
  10. with sm: # 类似于sm.acquire() # 同一时间可以来3个人,1个人,或者2个人
  11. print('%s in' %currentThread().getName())
  12. time.sleep(random.randint(1,3))
  13.  
  14. if __name__ == '__main__':
  15. for i in range(10):
  16. t=Thread(target=task)
  17. t.start()
  18. """
  19. Thread-1 in
  20. Thread-2 in
  21. Thread-3 in
  22.  
  23. Thread-4 in
  24.  
  25. Thread-6 in
  26. Thread-5 in
  27. Thread-7 in
  28.  
  29. Thread-8 in
  30. Thread-9 in
  31.  
  32. Thread-10 in
  33. """
  1. 5.Event:
    多个线程之间同步的,一个线程告诉另一些线程可以做其他的活了
    event.wait()
    event.wait(2)
    event.set()
    event.is_set()
    event.clear()
  1. from threading import Thread,Event
  2. import time
  3.  
  4. event=Event()
  5. # event.wait() # 等 ...直到 set
  6. # event.set()
  7.  
  8. def student(name):
  9. print('学生%s 正在听课' %name)
  10. # event.wait() # 学生要等7秒 才能下课
  11. event.wait(2) # 学生等2秒 直接下课了
  12.  
  13. print('学生%s 课间活动' %name)
  14.  
  15. def teacher(name):
  16. print('老师%s 正在授课' %name)
  17. time.sleep(7)
  18. event.set()
  19.  
  20. if __name__ == '__main__':
  21. stu1=Thread(target=student,args=('alex',))
  22. stu2=Thread(target=student,args=('wxx',))
  23. stu3=Thread(target=student,args=('yxx',))
  24. t1=Thread(target=teacher,args=('egon',))
  25.  
  26. stu1.start()
  27. stu2.start()
  28. stu3.start()
  29. t1.start()
  30.  
  31. # ------------------
  32. # 设置链接的超时时间
  33. from threading import Thread,Event,currentThread
  34. import time
  35.  
  36. event=Event()
  37.  
  38. def conn():
  39. # print('%s is connecting'%currentThread().getName())
  40. # event.wait()
  41. # print('%s is connected'%currentThread().getName())
  42.  
  43. n=0
  44. while not event.is_set():
  45. if n == 3:
  46. print('%s try too many times' %currentThread().getName())
  47. return
  48. print('%s try %s' %(currentThread().getName(),n))
  49. event.wait(0.5)
  50. n+=1
  51.  
  52. print('%s is connected' %currentThread().getName())
  53.  
  54. def check():
  55. print('%s is checking' %currentThread().getName())
  56. time.sleep(5)
  57. event.set()
  58.  
  59. if __name__ == '__main__':
  60. for i in range(3):
  61. t=Thread(target=conn)
  62. t.start()
  63. t=Thread(target=check)
  64. t.start()
  65. """
  66. Thread-1 try 0
  67. Thread-2 try 0
  68. Thread-3 try 0
  69. Thread-4 is checking
  70. Thread-3 try 1
  71. Thread-2 try 1
  72. Thread-1 try 1
  73. Thread-3 try 2
  74. Thread-1 try 2
  75. Thread-2 try 2
  76. Thread-3 try too many times
  77. Thread-2 try too many times
  78. Thread-1 try too many times
  79. """
  1. 6.定时器:Timer
      t=Timer(5,task,args=('egon',))
      t.start()
      t.cancel()
  1. from threading import Timer
  2.  
  3. def task(name):
  4. print('hello %s' %name)
  5.  
  6. t=Timer(5,task,args=('egon',)) # 就是起了一个线程
  7. t.start()
  8.  
  9. # ----------------------
  10. from threading import Timer
  11. import random
  12.  
  13. class Code:
  14. def __init__(self):
  15. self.make_cache()
  16.  
  17. def make_cache(self,interval=10):
  18. self.cache=self.make_code()
  19. print(self.cache)
  20. self.t=Timer(interval,self.make_cache)
  21. self.t.start()
  22.  
  23. def make_code(self,n=4):
  24. res=''
  25. for i in range(n):
  26. s1=str(random.randint(0,9))
  27. s2=chr(random.randint(65,90))
  28. res+=random.choice([s1,s2])
  29. return res
  30.  
  31. def check(self):
  32. while True:
  33. code=input('请输入你的验证码>>: ').strip()
  34. if code.upper() == self.cache:
  35. print('验证码输入正确')
  36. self.t.cancel()
  37. break
  38.  
  39. obj=Code()
  40. obj.check()
  1.  

并发编程 - 线程 - 1.互斥锁/2.GIL解释器锁/3.死锁与递归锁/4.信号量/5.Event事件/6.定时器的更多相关文章

  1. [并发编程 - 多线程:信号量、死锁与递归锁、时间Event、定时器Timer、线程队列、GIL锁]

    [并发编程 - 多线程:信号量.死锁与递归锁.时间Event.定时器Timer.线程队列.GIL锁] 信号量 信号量Semaphore:管理一个内置的计数器 每当调用acquire()时内置计数器-1 ...

  2. 10 并发编程-(线程)-GIL全局解释器锁&死锁与递归锁

    一.GIL全局解释器锁 1.引子 在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势 首先需要明确的一点是GIL并不是Python的特性,它是在实现Pyt ...

  3. 并发编程-线程-死锁现象-GIL全局锁-线程池

    一堆锁 死锁现象 (重点) 死锁指的是某个资源被占用后,一直得不到释放,导致其他需要这个资源的线程进入阻塞状态. 产生死锁的情况 对同一把互斥锁加了多次 一个共享资源,要访问必须同时具备多把锁,但是这 ...

  4. 并发编程(五)——GIL全局解释器锁、死锁现象与递归锁、信号量、Event事件、线程queue

    GIL.死锁现象与递归锁.信号量.Event事件.线程queue 一.GIL全局解释器锁 1.什么是全局解释器锁 GIL本质就是一把互斥锁,相当于执行权限,每个进程内都会存在一把GIL,同一进程内的多 ...

  5. Python并发编程-进程 线程 同步锁 线程死锁和递归锁

    进程是最小的资源单位,线程是最小的执行单位 一.进程 进程:就是一个程序在一个数据集上的一次动态执行过程. 进程由三部分组成: 1.程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成 2.数据 ...

  6. TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q

    TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q 一.TCP协议下的服务端并发 ''' 将不同的功能尽量拆分成不同的函数,拆分出来的功能可以被多个地方使用 TCP服务 ...

  7. Java并发编程实战 03互斥锁 解决原子性问题

    文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...

  8. Python并发编程-线程锁

    互斥锁-Lock #多线程中虽然有GIL,但是还是有可能产生数据不安全,故还需加锁 from threading import Lock, Thread #互斥锁 import time def ea ...

  9. python并发编程之线程(二):死锁和递归锁&信号量&定时器&线程queue&事件evevt

    一 死锁现象与递归锁 进程也有死锁与递归锁,在进程那里忘记说了,放到这里一切说了额 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将 ...

随机推荐

  1. 结构体内重载小于号< 及构造函数

    struct Node { int d, e; bool operator < (const Node x) const { return x.d < d; } Node(int d, i ...

  2. [pwm]PWM的输入捕捉模式

    对于stm32来说,输入捕捉模式有两种: 普通输入捕捉模式:经常用来测量脉冲宽度和频率,例如测量脉冲宽度,TIM5_CH1来捕获高电平脉宽,首先先设置输入捕获为上升沿触发,然后记录下发生上升沿时TIM ...

  3. 使用js事件机制进行通用操作&特定业务处理的协调

    背景:提供一个通用的功能工具条,工具条会在特定的事件响应时进行一些通用处理:第三方系统使用iframe嵌入这个工具条中,在工具条的特定的事件响应时进行通用处理的时候,有可能第三方系统会有一些自己的业务 ...

  4. 介绍编译的less的几种IDE工具

    介绍编译的less的两种IDE工具 现在css预编译越来越普及了,著名的有less.sass.stylus等等等等.功能上基本上都是大同小异.这些个玩意儿主要表达的意思就是:“像编程一样的编写你的cs ...

  5. hdu4746 Mophues 莫比乌斯

    /** 题目:hdu4746 Mophues 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4746 题意:求x,y在给定范围内gcd(x,y)分解素因子的 ...

  6. C#三种模拟自动登录和提交POST信息的实现方法【转】

    网页自动登录(提交Post内容)的用途很多,如验证身份.程序升级.网络投票等,以下是用C#实现的方法.       网页自动登录和提交POST信息的核心就是分析网页的源代码(HTML),在C#中,可以 ...

  7. Wamp2.5 64bit,无法改动MySQL datadir位置

    今天偶然想到去更新一下机子里面PHP的版本号,然后又一次去wamp官网下载了WAMP(wamp 64  Apache : 2.4.9 MySQL : 5.6.17 PHP : 5.5.12 PHPMy ...

  8. C# 中的treeview绑定数据库(递归算法)

    近日面试的给我两道题目,一道是IQ测试,第二个就是题目所言 总共两个表 department(id int not null primary key,parentid int,name char(50 ...

  9. 经典SQL面试题(转)

    http://www.cnblogs.com/kcher90/archive/2013/03/13/2957932.html 有三个表,如果学生缺考,那么在成绩表中就不存在这个学生的这门课程成绩的记录 ...

  10. error C2678: 二进制“+”: 没有找到接受“const char [22]”类型的左操作数的运算符(或没有可接受的转换)没有与这些操作数匹配的“+”运算符

    错误:没有与这些操作数匹配的“+”运算符,操作数类型为const char [20]+CString 分析原因:其提示操作数类型为const char [20]+CString 可见是类型有问题 故加 ...