一、同步锁

1.1 多个线程抢占资源的情况

  1. from threading import Thread
  2. import os,time
  3. def work():
  4. global n
  5. temp=n
  6. time.sleep(0.1)
  7. n=temp-1
  8. if __name__ == '__main__':
  9. n=100
  10. l=[]
  11. for i in range(100):
  12. p=Thread(target=work)
  13. l.append(p)
  14. p.start()
  15. for p in l:
  16. p.join()
  17. print(n) #结果可能为99

1.1.1 对公共数据的操作

  1. import threading
  2. R=threading.Lock()
  3. R.acquire()
  4. '''
  5. 对公共数据的操作
  6. '''
  7. R.release()

1.2 同步锁的引用

  1. from threading import Thread,Lock
  2. import os,time
  3. def work():
  4. global n
  5. lock.acquire()
  6. temp=n
  7. time.sleep(0.1)
  8. n=temp-1
  9. lock.release()
  10. if __name__ == '__main__':
  11. lock=Lock()
  12. n=100
  13. l=[]
  14. for i in range(100):
  15. p=Thread(target=work)
  16. l.append(p)
  17. p.start()
  18. for p in l:
  19. p.join()
  20. print(n) #结果肯定为0,由原来的并发执行变成串行,牺牲了执行效率保证了数据安全

1.3 互斥锁与join的区别

  1. #不加锁:并发执行,速度快,数据不安全
  2. from threading import current_thread,Thread,Lock
  3. import os,time
  4. def task():
  5. global n
  6. print('%s is running' %current_thread().getName())
  7. temp=n
  8. time.sleep(0.5)
  9. n=temp-1
  10. if __name__ == '__main__':
  11. n=100
  12. lock=Lock()
  13. threads=[]
  14. start_time=time.time()
  15. for i in range(100):
  16. t=Thread(target=task)
  17. threads.append(t)
  18. t.start()
  19. for t in threads:
  20. t.join()
  21. stop_time=time.time()
  22. print('主:%s n:%s' %(stop_time-start_time,n))
  23. '''
  24. Thread-1 is running
  25. Thread-2 is running
  26. ......
  27. Thread-100 is running
  28. 主:0.5216062068939209 n:99
  29. '''
  30. #不加锁:未加锁部分并发执行,加锁部分串行执行,速度慢,数据安全
  31. from threading import current_thread,Thread,Lock
  32. import os,time
  33. def task():
  34. #未加锁的代码并发运行
  35. time.sleep(3)
  36. print('%s start to run' %current_thread().getName())
  37. global n
  38. #加锁的代码串行运行
  39. lock.acquire()
  40. temp=n
  41. time.sleep(0.5)
  42. n=temp-1
  43. lock.release()
  44. if __name__ == '__main__':
  45. n=100
  46. lock=Lock()
  47. threads=[]
  48. start_time=time.time()
  49. for i in range(100):
  50. t=Thread(target=task)
  51. threads.append(t)
  52. t.start()
  53. for t in threads:
  54. t.join()
  55. stop_time=time.time()
  56. print('主:%s n:%s' %(stop_time-start_time,n))
  57. '''
  58. Thread-1 is running
  59. Thread-2 is running
  60. ......
  61. Thread-100 is running
  62. 主:53.294203758239746 n:0
  63. '''
  64. # 有的同学可能有疑问:既然加锁会让运行变成串行,那么我在start之后立即使用join,就不用加锁了啊,也是串行的效果啊
  65. # 没错:在start之后立刻使用jion,肯定会将100个任务的执行变成串行,毫无疑问,最终n的结果也肯定是0,是安全的,但问题是
  66. # start后立即join:任务内的所有代码都是串行执行的,而加锁,只是加锁的部分即修改共享数据的部分是串行的
  67. # 单从保证数据安全方面,二者都可以实现,但很明显是加锁的效率更高.
  68. from threading import current_thread,Thread,Lock
  69. import os,time
  70. def task():
  71. time.sleep(3)
  72. print('%s start to run' %current_thread().getName())
  73. global n
  74. temp=n
  75. time.sleep(0.5)
  76. n=temp-1
  77. if __name__ == '__main__':
  78. n=100
  79. lock=Lock()
  80. start_time=time.time()
  81. for i in range(100):
  82. t=Thread(target=task)
  83. t.start()
  84. t.join()
  85. stop_time=time.time()
  86. print('主:%s n:%s' %(stop_time-start_time,n))
  87. '''
  88. Thread-1 start to run
  89. Thread-2 start to run
  90. ......
  91. Thread-100 start to run
  92. 主:350.6937336921692 n:0 #耗时是多么的恐怖
  93. '''

二、死锁与递归锁

进程也有死锁与递归锁,在进程那里忘记说了,放到这里一起说了。

所谓死锁:是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁

2.1 死锁

  1. from threading import Lock as Lock
  2. import time
  3. mutexA=Lock()
  4. mutexA.acquire()
  5. mutexA.acquire()
  6. print(123)
  7. mutexA.release()
  8. mutexA.release()

解决方法:递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。

这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁。

2.2 递归锁RLock

  1. from threading import RLock as Lock
  2. import time
  3. mutexA=Lock()
  4. mutexA.acquire()
  5. mutexA.acquire()
  6. print(123)
  7. mutexA.release()
  8. mutexA.release()

三、典型问题:科学家吃面

3.1 死锁问题

  1. import time
  2. from threading import Thread,Lock
  3. noodle_lock = Lock()
  4. fork_lock = Lock()
  5. def eat1(name):
  6. noodle_lock.acquire()
  7. print('%s 抢到了面条'%name)
  8. fork_lock.acquire()
  9. print('%s 抢到了叉子'%name)
  10. print('%s 吃面'%name)
  11. fork_lock.release()
  12. noodle_lock.release()
  13. def eat2(name):
  14. fork_lock.acquire()
  15. print('%s 抢到了叉子' % name)
  16. time.sleep(1)
  17. noodle_lock.acquire()
  18. print('%s 抢到了面条' % name)
  19. print('%s 吃面' % name)
  20. noodle_lock.release()
  21. fork_lock.release()
  22. for name in ['哪吒','nick','tank']:
  23. t1 = Thread(target=eat1,args=(name,))
  24. t2 = Thread(target=eat2,args=(name,))
  25. t1.start()
  26. t2.start()

3.2 递归锁解决死锁问题

  1. import time
  2. from threading import Thread,RLock
  3. fork_lock = noodle_lock = RLock()
  4. def eat1(name):
  5. noodle_lock.acquire()
  6. print('%s 抢到了面条'%name)
  7. fork_lock.acquire()
  8. print('%s 抢到了叉子'%name)
  9. print('%s 吃面'%name)
  10. fork_lock.release()
  11. noodle_lock.release()
  12. def eat2(name):
  13. fork_lock.acquire()
  14. print('%s 抢到了叉子' % name)
  15. time.sleep(1)
  16. noodle_lock.acquire()
  17. print('%s 抢到了面条' % name)
  18. print('%s 吃面' % name)
  19. noodle_lock.release()
  20. fork_lock.release()
  21. for name in ['哪吒','nick','tank']:
  22. t1 = Thread(target=eat1,args=(name,))
  23. t2 = Thread(target=eat2,args=(name,))
  24. t1.start()
  25. t2.start()

Python程序中的线程操作-锁的更多相关文章

  1. Python程序中的线程操作(线程池)-concurrent模块

    目录 Python程序中的线程操作(线程池)-concurrent模块 一.Python标准模块--concurrent.futures 二.介绍 三.基本方法 四.ProcessPoolExecut ...

  2. 30、Python程序中的线程操作(oncurrent模块)

    进程是cpu资源分配的最小单元,一个进程中可以有多个线程. 线程是cpu计算的最小单元. 对于Python来说他的进程和线程和其他语言有差异,是有GIL锁. GIL锁 GIL锁保证一个进程中同一时刻只 ...

  3. Python程序中的线程操作-创建多线程

    目录 一.python线程模块的选择 二.threading模块 三.通过threading.Thread类创建线程 3.1 创建线程的方式一 3.2 创建线程的方式二 四.多线程与多进程 4.1 p ...

  4. Python程序中的线程操作-concurrent模块

    目录 一.Python标准模块--concurrent.futures 二.介绍 三.基本方法 四.ProcessPoolExecutor 五.ThreadPoolExecutor 六.map的用法 ...

  5. Python程序中的线程操作-守护线程

    目录 一.守护线程 1.1 详细解释 1.2 守护线程例1 1.3 守护线程例2 一.守护线程 无论是进程还是线程,都遵循:守护xx会等待主xx运行完毕后被销毁.需要强调的是:运行完毕并非终止运行. ...

  6. Python程序中的线程操作-线程队列

    目录 一.线程队列 二.先进先出 三.后进先出 四.存储数据时可设置优先级的队列 4.1 优先级队列 4.2 更多方法说明 一.线程队列 queue队列:使用import queue,用法与进程Que ...

  7. 在Python程序中的进程操作,multiprocess.Process模块

    在python程序中的进程操作 之前我们已经了解了很多进程相关的理论知识,了解进程是什么应该不再困难了,刚刚我们已经了解了,运行中的程序就是一个进程.所有的进程都是通过它的父进程来创建的.因此,运行起 ...

  8. python 全栈开发,Day38(在python程序中的进程操作,multiprocess.Process模块)

    昨日内容回顾 操作系统纸带打孔计算机批处理 —— 磁带 联机 脱机多道操作系统 —— 极大的提高了CPU的利用率 在计算机中 可以有超过一个进程 进程遇到IO的时候 切换给另外的进程使用CPU 数据隔 ...

  9. Python程序中的进程操作--—--开启多进程

    Python程序中的进程操作-----开启多进程 之前我们已经了解了很多进程相关的理论知识,了解进程是什么应该不再困难了,刚刚我们已经了解了,运行中的程序就是一个进程.所有的进程都是通过它的父进程来创 ...

随机推荐

  1. ES6-WeakSet数组结构

    WeakSet 也会去重 总结: 1.成员都是对象: 2.成员都是弱引用,可以被垃圾回收机制回收,可以用来保存 DOM 节点,不容易造成内存泄漏: 3.不能遍历,方法有 add.delete.has. ...

  2. SQL实用技巧:如何判断一个值是否为数字的方法

    检测是不是数字型的数据, 两种方法 1. ISNUMERIC ( expression ) 2. PATINDEX ( ‘%pattern%‘ , expression ) 1. ISNUMERIC  ...

  3. latex 添加Bibtex 全解(使用TeXstudio)

    前提知识: 生成pdf的一般流程 在使用Latex之前,我们一般会借用已有的论文模板,在模板基础上加入我们自己的文章内容,随后编译成PDF文件,其基本流程就是:Latex->Bibtex-> ...

  4. AlertDialog创建对话框的测试

    AlertDialog的功能是非常强大的,它可以创建各种对话框,它的结构分为:图标区.标题区.内容区.按钮区共四个区域.以这样的思路区创建AlertDialog是非常简单的. 创建AlertDialo ...

  5. Spring整合JMS消息中间件

    1. 点对点模式 1.1消息生产者 (1)创建工程springjms_producer,在POM文件中引入SpringJms .activeMQ以及单元测试相关依赖 (2)在src/main/reso ...

  6. python判断文件夹和文件是否存在

    1.os.path.exists()既可以判断文件是否存在,又可以判断文件夹是否存在 2.os.path.isfile()判断文件是否存在 3.os.path.isdir()判断文件夹是否存在

  7. io流追加到一个文件中信息比如日志

    package com.yh.day02.arrays; import java.io.File;import java.io.FileInputStream;import java.io.FileN ...

  8. Bandizip解压压缩软件

    上次重装系统以后,特别注意安装软件,在这里提一些比较好的 解压软件:Bandizip 这个是一个免费轻量级的软件,压缩解压速度快,没什么广告,推荐大家在官方下载 Bandizip下载网址 点击下载安装 ...

  9. C sharp #005# 对象与对象变量

    饮水思源:金老师的自学网站 索引 自动装箱 “只读”对象 设定启动窗体 ShowDialog与Show 自动装箱 基本类型的变量值可以自动装箱到一个object对象中, 反过来,object对象也可以 ...

  10. 清新简约风格毕业论文答辩PPT模板推荐

    不管是学生还是老师,应该经常会需要学生答辩的PPT模板,今天给大家推荐织梦58的学生答辩ppt模板. 模版来源:http://ppt.dede58.com/gongzuohuibao/26494.ht ...