Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 256|回复: 0

[默认分类] 并发编程 - 线程 - 1.互斥锁/2.GIL解释器锁/3.死锁与递归锁/4.信号量/5.Event事件/6.定时器

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-4-4 10:45:35 | 显示全部楼层 |阅读模式
    1. 1.互斥锁:
    2.     原理:将并行变成串行
    3.     精髓:局部串行,只针对共享数据修改
    4.           保护不同的数据就应该用不用的锁
    复制代码


    1. 1 from threading import Thread, Lock
    2. 2 import time
    3. 3
    4. 4 n = 100
    5. 5
    6. 6 def task():
    7. 7     global n
    8. 8     mutex.acquire()  # 效率低了 但是数据安全了
    9. 9     temp = n
    10. 10     time.sleep(0.1)  # 100个线程 都拿到了100  所以就是 100个线程100-1
    11. 11     n = temp - 1
    12. 12     mutex.release()
    13. 13
    14. 14
    15. 15 if __name__ == "__main__":
    16. 16     mutex = Lock()
    17. 17     t_l = []
    18. 18     for i in range(100):
    19. 19         t = Thread(target=task)
    20. 20         t_l.append(t)
    21. 21         t.start()
    22. 22
    23. 23     for t in t_l:
    24. 24         t.join()
    25. 25
    26. 26     print("主", n)
    27. 27 """
    28. 28 主 99   原因: 100个线程 都拿到了100  所以就是 100个线程100-1  数据不安全 效率高但是不安全
    29. 29           要将并行改为串行
    30. 30 """
    31. 31 """
    32. 32 主 0    原因:效率低了 但是数据安全了
    33. 33 """
    复制代码

    1. 2.GIL: global interpreter lock
    2.     python3 test.py
    3.     ps aux | grep test     # linux
    4.     tasklist | findstr python   # windows  python.exe
    5. 运行python 会有几步:
    6.     1.会有一个进程,进程内存空间 python解释器的代码先加载到内存空间
    7.     2.test.py 内容加载到内存
    8.     3.解释执行;代码交给了python解释器
    9.         线程干活指向了python代码 python代码当作参数传给了解释器
    10.         线程拿到解释器的代码,拿着python代码当作参数,执行
    11.         垃圾回收线程运行解释器的代码
    12.         垃圾回收线程和某一个线程冲突了,数据不安全,
    13.    
    复制代码


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


      
    1.    总结:
    2.         1.GIL 一个进程内的多个线程同一时间只能运行一个线程,垃圾回收线程是安全的
    3.         2.针对不同的数据,就应该加不同的锁,解释器级别的GIL锁,只能保护解释器级别的数据,
    4.           不能保护自己的数据,针对自己的共享数据还要加锁;
    5.           线程首先抢的是;GIL锁,之后才是mutex
    6.    官网:
    7.       结论:在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势
    8.    GIL的存在:同一时刻,只能有一个线程在运行
    9.         多核,多进程,但进程开销大,多线程,又不能用多核 ?
    10.    cpu干计算的,多个cpu
    11.         1.如果是干计算的操作,多核省时间
    12.         2.如果干IO阻塞型操作,多核没用
    13.    程序运行:都会干计算和IO操作
    14.    四个任务:
    15.         1.1个核:开多线程  ,因为多进程能用上多核
    16.         2.多核:
    17.             计算密集型:用多进程,用多核,eg:金融行业的,计算比较多,虽然多进程开销大,但多核,保证了计算快
    18.             IO密集型:用多线程,同一时间只能用一个核,1个核一个进程,多线程就在一个核上来回切和四个核来回切是一样的
    19.    现在写的软件:
    20.       网络打交道,网络的IO
    21.       IO密集型,用多线程
    复制代码


    1. 1 """
    2. 2 计算密集型应该用: 多进程 效率高  
    3. 3 """
    4. 4 from multiprocessing import Process
    5. 5 from threading import Thread
    6. 6 import os,time
    7. 7
    8. 8 def work():
    9. 9     res=0
    10. 10     for i in range(100000000):
    11. 11         res*=i
    12. 12
    13. 13
    14. 14 if __name__ == "__main__":
    15. 15     l=[]
    16. 16     print(os.cpu_count()) #本机为8核
    17. 17     start=time.time()
    18. 18     for i in range(8):
    19. 19         # p=Process(target=work) #耗时8s多
    20. 20         p=Thread(target=work) #耗时37s多
    21. 21         l.append(p)
    22. 22         p.start()
    23. 23     for p in l:
    24. 24         p.join()
    25. 25     stop=time.time()
    26. 26     print("run time is %s" %(stop-start))
    27. 27
    28. 28 """
    29. 29 IO密集型:多线程 效率高
    30. 30 """
    31. 31 from multiprocessing import Process
    32. 32 from threading import Thread
    33. 33 import threading
    34. 34 import os,time
    35. 35 def work():
    36. 36     time.sleep(2)
    37. 37     print("===>")
    38. 38
    39. 39 if __name__ == "__main__":
    40. 40     l=[]
    41. 41     print(os.cpu_count()) #本机为8核
    42. 42     start=time.time()
    43. 43     for i in range(400):
    44. 44         # p=Process(target=work) #耗时8s多,大部分时间耗费在创建进程上
    45. 45         p=Thread(target=work) #耗时2s多
    46. 46         l.append(p)
    47. 47         p.start()
    48. 48     for p in l:
    49. 49         p.join()
    50. 50     stop=time.time()
    51. 51     print("run time is %s" %(stop-start))
    复制代码

    1. 3.死锁:
    2.     你拿着我的锁,我拿着你的锁
    3. 互斥锁:Lock()
    4.     互斥锁只能acquire一次
    5. 递归锁:RLock()
    6.     可以连续acquire多次,每acquire一次计数器+1,
    7.     只有计数为0时,才能被抢到acquire
    复制代码


    1. 1 from threading import Thread,Lock
    2. 2 import time
    3. 3
    4. 4 mutexA=Lock()
    5. 5 mutexB=Lock()
    6. 6
    7. 7 class MyThread(Thread):
    8. 8     def run(self):
    9. 9         self.f1()
    10. 10         self.f2()
    11. 11
    12. 12     def f1(self):
    13. 13         mutexA.acquire()
    14. 14         print("%s 拿到了A锁" %self.name)
    15. 15
    16. 16         mutexB.acquire()
    17. 17         print("%s 拿到了B锁" %self.name)
    18. 18         mutexB.release()
    19. 19
    20. 20         mutexA.release()
    21. 21
    22. 22
    23. 23     def f2(self):
    24. 24         mutexB.acquire()
    25. 25         print("%s 拿到了B锁" % self.name)
    26. 26         time.sleep(0.1)
    27. 27
    28. 28         mutexA.acquire()
    29. 29         print("%s 拿到了A锁" % self.name)
    30. 30         mutexA.release()
    31. 31
    32. 32         mutexB.release()
    33. 33
    34. 34 if __name__ == "__main__":
    35. 35     for i in range(10):
    36. 36         t=MyThread()
    37. 37         t.start()
    38. 38 """
    39. 39 Thread-1 拿到了A锁  # 死锁了 卡住了
    40. 40 Thread-1 拿到了B锁
    41. 41 Thread-1 拿到了B锁
    42. 42 Thread-2 拿到了A锁
    43. 43 """
    复制代码



    1. 1 # 互斥锁只能acquire一次
    2. 2 # from threading import Thread,Lock
    3. 3 #
    4. 4 # mutexA=Lock()
    5. 5 #
    6. 6 # mutexA.acquire()
    7. 7 # mutexA.release()
    8. 8
    9. 9 # 递归锁:可以连续acquire多次,每acquire一次计数器+1,只有计数为0时,才能被抢到acquire
    10. 10 from threading import Thread,RLock
    11. 11 import time
    12. 12
    13. 13 mutexB=mutexA=RLock()
    14. 14
    15. 15 class MyThread(Thread):
    16. 16     def run(self):
    17. 17         self.f1()
    18. 18         self.f2()
    19. 19
    20. 20     def f1(self):
    21. 21         mutexA.acquire()
    22. 22         print("%s 拿到了A锁" %self.name)
    23. 23
    24. 24         mutexB.acquire()
    25. 25         print("%s 拿到了B锁" %self.name)
    26. 26         mutexB.release()
    27. 27
    28. 28         mutexA.release()
    29. 29
    30. 30
    31. 31     def f2(self):
    32. 32         mutexB.acquire()
    33. 33         print("%s 拿到了B锁" % self.name)
    34. 34         time.sleep(2)
    35. 35
    36. 36         mutexA.acquire()
    37. 37         print("%s 拿到了A锁" % self.name)
    38. 38         mutexA.release()
    39. 39
    40. 40         mutexB.release()
    41. 41
    42. 42 if __name__ == "__main__":
    43. 43     for i in range(10):
    44. 44         t=MyThread()
    45. 45         t.start()
    46. 46 """
    47. 47 Thread-1 拿到了A锁  # 解决了 死锁
    48. 48 Thread-1 拿到了B锁
    49. 49 Thread-1 拿到了B锁
    50. 50 Thread-1 拿到了A锁
    51. 51 Thread-2 拿到了A锁
    52. 52 Thread-2 拿到了B锁
    53. 53 Thread-2 拿到了B锁
    54. 54 Thread-2 拿到了A锁
    55. 55 Thread-4 拿到了A锁
    56. 56 Thread-4 拿到了B锁
    57. 57 Thread-5 拿到了A锁
    58. 58 Thread-5 拿到了B锁
    59. 59 Thread-5 拿到了B锁
    60. 60 Thread-5 拿到了A锁
    61. 61 Thread-7 拿到了A锁
    62. 62 Thread-7 拿到了B锁
    63. 63 Thread-7 拿到了B锁
    64. 64 Thread-7 拿到了A锁
    65. 65 Thread-9 拿到了A锁
    66. 66 Thread-9 拿到了B锁
    67. 67 Thread-9 拿到了B锁
    68. 68 Thread-9 拿到了A锁
    69. 69 Thread-3 拿到了A锁
    70. 70 Thread-3 拿到了B锁
    71. 71 Thread-3 拿到了B锁
    72. 72 Thread-3 拿到了A锁
    73. 73 Thread-6 拿到了A锁
    74. 74 Thread-6 拿到了B锁
    75. 75 Thread-6 拿到了B锁
    76. 76 Thread-6 拿到了A锁
    77. 77 Thread-10 拿到了A锁
    78. 78 Thread-10 拿到了B锁
    79. 79 Thread-10 拿到了B锁
    80. 80 Thread-10 拿到了A锁
    81. 81 Thread-8 拿到了A锁
    82. 82 Thread-8 拿到了B锁
    83. 83 Thread-8 拿到了B锁
    84. 84 Thread-8 拿到了A锁
    85. 85 Thread-4 拿到了B锁
    86. 86 Thread-4 拿到了A锁
    87. 87 """
    复制代码

    1. 4.信号量
    2.   信号量也是一把锁,可以指定信号量为5,对比互斥锁同一时间只能有一个任务抢到锁去执行,
    3.       信号量同一时间可以有5个任务拿到锁去执行
    4.       信号量:同一时间有多个线程在进行
    复制代码


    1. 1 from threading import Thread,Semaphore,currentThread
    2. 2 import time,random
    3. 3
    4. 4 sm=Semaphore(1)
    5. 5
    6. 6 def task():
    7. 7     # sm.acquire()
    8. 8     # print("%s in" %currentThread().getName())
    9. 9     # sm.release()
    10. 10     with sm:  # 类似于sm.acquire() # 同一时间可以来3个人,1个人,或者2个人
    11. 11         print("%s in" %currentThread().getName())
    12. 12         time.sleep(random.randint(1,3))
    13. 13
    14. 14
    15. 15 if __name__ == "__main__":
    16. 16     for i in range(10):
    17. 17         t=Thread(target=task)
    18. 18         t.start()
    19. 19 """
    20. 20 Thread-1 in
    21. 21 Thread-2 in
    22. 22 Thread-3 in
    23. 23
    24. 24 Thread-4 in
    25. 25
    26. 26
    27. 27 Thread-6 in
    28. 28 Thread-5 in
    29. 29 Thread-7 in
    30. 30
    31. 31
    32. 32 Thread-8 in
    33. 33 Thread-9 in
    34. 34
    35. 35 Thread-10 in
    36. 36 """
    复制代码

    1. 5.Event:
    2.    多个线程之间同步的,一个线程告诉另一些线程可以做其他的活了
    3.    event.wait()
    4.    event.wait(2)
    5.    event.set()
    6.    event.is_set()
    7.    event.clear()
    复制代码


    1. 1 from threading import Thread,Event
    2. 2 import time
    3. 3
    4. 4 event=Event()
    5. 5 # event.wait()   # 等 ...直到 set
    6. 6 # event.set()
    7. 7
    8. 8
    9. 9 def student(name):
    10. 10     print("学生%s 正在听课" %name)
    11. 11     # event.wait()  # 学生要等7秒 才能下课
    12. 12     event.wait(2)   # 学生等2秒 直接下课了
    13. 13
    14. 14     print("学生%s 课间活动" %name)
    15. 15
    16. 16
    17. 17 def teacher(name):
    18. 18     print("老师%s 正在授课" %name)
    19. 19     time.sleep(7)
    20. 20     event.set()
    21. 21
    22. 22
    23. 23 if __name__ == "__main__":
    24. 24     stu1=Thread(target=student,args=("alex",))
    25. 25     stu2=Thread(target=student,args=("wxx",))
    26. 26     stu3=Thread(target=student,args=("yxx",))
    27. 27     t1=Thread(target=teacher,args=("egon",))
    28. 28
    29. 29     stu1.start()
    30. 30     stu2.start()
    31. 31     stu3.start()
    32. 32     t1.start()
    33. 33
    34. 34
    35. 35 # ------------------
    36. 36 # 设置链接的超时时间
    37. 37 from threading import Thread,Event,currentThread
    38. 38 import time
    39. 39
    40. 40 event=Event()
    41. 41
    42. 42 def conn():
    43. 43     # print("%s is connecting"%currentThread().getName())
    44. 44     # event.wait()
    45. 45     # print("%s is connected"%currentThread().getName())
    46. 46
    47. 47     n=0
    48. 48     while not event.is_set():
    49. 49         if n == 3:
    50. 50             print("%s try too many times" %currentThread().getName())
    51. 51             return
    52. 52         print("%s try %s" %(currentThread().getName(),n))
    53. 53         event.wait(0.5)
    54. 54         n+=1
    55. 55
    56. 56     print("%s is connected" %currentThread().getName())
    57. 57
    58. 58
    59. 59 def check():
    60. 60     print("%s is checking" %currentThread().getName())
    61. 61     time.sleep(5)
    62. 62     event.set()
    63. 63
    64. 64
    65. 65 if __name__ == "__main__":
    66. 66     for i in range(3):
    67. 67         t=Thread(target=conn)
    68. 68         t.start()
    69. 69     t=Thread(target=check)
    70. 70     t.start()
    71. 71 """
    72. 72 Thread-1 try 0
    73. 73 Thread-2 try 0
    74. 74 Thread-3 try 0
    75. 75 Thread-4 is checking
    76. 76 Thread-3 try 1
    77. 77 Thread-2 try 1
    78. 78 Thread-1 try 1
    79. 79 Thread-3 try 2
    80. 80 Thread-1 try 2
    81. 81 Thread-2 try 2
    82. 82 Thread-3 try too many times
    83. 83 Thread-2 try too many times
    84. 84 Thread-1 try too many times
    85. 85 """
    复制代码

    1. 6.定时器:Timer
    2.   t=Timer(5,task,args=("egon",))
    3.   t.start()
    4.   t.cancel()
    复制代码


    1. 1 from threading import Timer
    2. 2
    3. 3 def task(name):
    4. 4     print("hello %s" %name)
    5. 5
    6. 6 t=Timer(5,task,args=("egon",))  # 就是起了一个线程
    7. 7 t.start()
    8. 8
    9. 9 # ----------------------
    10. 10 from threading import Timer
    11. 11 import random
    12. 12
    13. 13 class Code:
    14. 14     def __init__(self):
    15. 15         self.make_cache()
    16. 16
    17. 17     def make_cache(self,interval=10):
    18. 18         self.cache=self.make_code()
    19. 19         print(self.cache)
    20. 20         self.t=Timer(interval,self.make_cache)
    21. 21         self.t.start()
    22. 22
    23. 23     def make_code(self,n=4):
    24. 24         res=""
    25. 25         for i in range(n):
    26. 26             s1=str(random.randint(0,9))
    27. 27             s2=chr(random.randint(65,90))
    28. 28             res+=random.choice([s1,s2])
    29. 29         return res
    30. 30
    31. 31     def check(self):
    32. 32         while True:
    33. 33             code=input("请输入你的验证码>>: ").strip()
    34. 34             if code.upper() == self.cache:
    35. 35                 print("验证码输入正确")
    36. 36                 self.t.cancel()
    37. 37                 break
    38. 38
    39. 39 obj=Code()
    40. 40 obj.check()
    复制代码

    复制代码
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-26 02:03 , Processed in 0.345112 second(s), 37 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表