在python的多线程和多进程中,当我们需要对多线程或多进程的共享资源或对象进行修改操作时,往往会出现因cpu随机调度而导致结果和我们预期不一致的问题,这时就需要对线程或者进程加锁,以保证一个线程或进程在对共享对象进行修改时,其他的线程或进程无法访问这个对象,直至获取锁的线程的操作执行完毕后释放锁。所以,锁在多线程和多进程中起到一个同步的作用,以保护每个线程和进程必要操作的完整执行。

python中,多线程和多进程的异同点主要在两大处:1、由于GIL机制,多线程只能实现并发,但多进程可以实现并行;2、同一个进程中的多线程是共享内存的,线程没有独立的内存,但是进程有独立的内存,所以多进程中的每个子进程是有自己的独立内存的,所以在多进程中,其之间的同名变量并不会冲突,是独立的。第一点异同往往决定我们的任务时该使用多进程还是多线程,如果是I/O密集型任务,考虑多线程,如果是计算密集型任务,考虑多进程;第二点异同会引出本文的重点,即两者在加锁的方式上是不一样的。

首先讲一下加锁的机制,其是如何实现线程或进程保护的。这个实现的大致过程为:首先在需要同步的代码块前面加上lock.acquire()语句,表示需要先成功获取该锁,才能继续执行下面的代码,然后在需要同步的代码块后面加上lock.release()语句,表示释放该锁。所以,如果当一个线程或进程获取该锁,而且该锁没有被释放的话,那么其他的线程或进程是无法成功获取该锁的,从而也就没法执行下面的同步代码块,从而起到保护作用,直至释放该锁,其他的线程或进程才可以成功获取该锁,然后继续执行下面的代码块。通过上述,一个明显的基本前提是,不同线程或进程面对的锁必须是同一把锁,即同步代码块前后的lock对象必须是同一个,不然如果每个线程或进程有自己不同的锁,那么这个锁也就自然起不到保护作用了。

由于多线程共享内存,所以我们只要在该进程中创建一个锁,然后锁定相应的代码块即可,因为内存的共享,使得不同子线程面对的就是同一把锁,如下代码所示。这样可以使得每个线程对x进行修改后,x最后依然保持原值。

from threading import Thread,Locklock=Lock()
x=1
def f(x):global xlock.acquire()x+=1x-=1lock.release()if __name=='__main__':t1=Thread(target=f,args=(1,))t2=Thread(target=f,args=(2,))t1.start()t2.start()t1.join()t2.join()

但是在多进程中,由于每个子进程都会有自己的独立内存,所以如果按以上方式创建进程,那么实际上在函数f中的lock对象会根据LEGB原则读取到外面的lock对象,也就是说lock=Lock()这条语句也会被包括进每个子进程中,从而每个子进程不仅会在内存创建函数f,也会创建自己独立的锁对象,这样违背了一锁原则,从而无法起到同步作用。所以多进程中正确的加锁方式应该是先在主进程中创建一个锁,然后以参数的形式传给每个进程,这样相当于不同的子进程面对的是同一个锁。虽然实际上,每个子进程还是会在自己的内存中保存自己的锁对象,即如果获取每个进程的锁的id,那么其id还是不同的,说明其是不同的对象,但是因为这个锁的对象是在主进程创建的,子进程只是在自己的内存中复制了主进程中锁的状态,所以尽管不同子进程内存中也有自己的锁对象,但是这个锁对象的状态是一样的,这是最本质的,即我们实际上是需要不同线程或进程的锁是同步的,状态是一致,就可以认为是同一把锁,从而可以实现保护作用。具体的实现方式见如下代码。这样可以实现一个进程的两个print都执行完之后,另一个进程才会print,这一般在I/O里面多进程文件写入时会遇到。

from multiprocessing import Process,Lock
import timedef f(x,lock):lock.acquire()print(x+'1',id(lock))time.sleep(5)print(x+'2',id(lock))lock.release()if __name__=='__main__':lock=Lock()p1=Process(target=f,args=('x',lock))p2=Process(target=f,args=('y',lock))p1.start()p2.start()p1.join()p2.join()

最后需要注意的一点是,创建多线程或多进程,都必须要先经过主模块判断,即必须在if __name__=='__main__':语句之后才行,这是为了保护资源的一种强制性机制。

python线程锁和进程锁相关推荐

  1. 分布式锁,进程锁,线程锁到底是什么

    在分布式集群系统的开发中,线程锁往往并不能支持全部场景的使用,必须引入新的技术方案分布式锁. 线程锁:大家都不陌生,主要用来给方法.代码块加锁.当某个方法或者代码块使用锁时,那么在同一时刻至多仅有有一 ...

  2. 一句话说清分布式锁,进程锁,线程锁

    一句话说清分布式锁,进程锁,线程锁 在分布式集群系统的开发中,线程锁往往并不能支持全部场景的使用,必须引入新的技术方案分布式锁. 线程锁,进程锁,分布式锁 线程锁:大家都不陌生,主要用来给方法.代码块 ...

  3. 正在等待缓存锁:无法获得锁_一句话说清分布式锁,进程锁,线程锁

    推荐阅读 1. Java 性能优化:教你提高代码运行的效率 2. Java问题排查工具清单 3. 记住:永远不要在MySQL中使用UTF-8 4. Springboot启动原理解析 在分布式集群系统的 ...

  4. 详解线程锁、进程锁、分布式锁以及数据库锁

    线程锁.进程锁.分布式锁以及数据库锁 1. 锁的介绍以及应用: 2. 定时器实现任务生产: 3. 手撕多线程任务队列: 视频讲解如下,点击观看: 线程锁.进程锁.分布式锁以及数据库锁丨C/C++丨Li ...

  5. 详解线程锁、进程锁以及分布式锁,开发过程中解决的具体问题

    聊聊线程锁.进程锁以及分布式锁 1. 线程锁-如何调度消费任务队列的线程池: 2. 进程锁-如何解决nginx惊群问题 3. 分布式锁-如何解决分布式系统中锁竞争问题 [Linux后端开发系列]详解线 ...

  6. 线程锁,进程锁以及分布式锁丨锁的实现及原理分析丨高效的使用

    线程锁.进程锁以及分布式锁 1. 线程锁 2. 进程锁 3. 分布式锁 [技术分享篇]线程锁,进程锁以及分布式锁丨锁的实现及原理分析丨高效的使用 更多精彩内容包括:C/C++,Linux,Nginx, ...

  7. 到底什么是分布式锁,进程锁,线程锁

    在分布式集群系统的开发中,线程锁往往并不能支持全部场景的使用,必须引入新的技术方案分布式锁. 线程锁 主要用来给方法.代码块加锁.当某个方法或者代码块使用锁时,那么在同一时刻至多仅有有一个线程在执行该 ...

  8. Python线程池与进程池

    Python线程池与进程池 前言 很多人学习python,不知道从何学起. 很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手. 很多已经做案例的人,却不知道如何去学习更加高深的知识 ...

  9. [Python]线程实例化;互斥锁;线程间通信

    目录 1.使用threading创建线程 2.线程锁(互斥锁) 线程间通信 ----------到此,结束------------ 图穷匕见 1.使用threading创建线程 threading模块 ...

  10. 什么是线程锁和进程锁?什么是死锁,死锁产生的原因和解决锁的办法

    线程锁:当多个线程几乎同时修改一个共享数据的时候,需要进行同步控制,线程同步能够保证多个线程安全的访问竞争资源(全局内容),最简单的同步机制就是使用互斥锁. 某个线程要更改共享数据时,先将其锁定,此时 ...

最新文章

  1. 多视图立体几何PatchMatchStereo:DSI与Cost Volume
  2. 这味儿上头,前有文言文,又来东北话,中文编程玩得挺得劲!
  3. 扩展iQuery使其支持多种编程语言(二) – 兼编译器的语法分析简介
  4. android 绘图软件,安卓最强大的绘图软件 妙笔生花最新评测
  5. 彰显城市等级的最典型代表,商业综合体城市PSD海报素材
  6. Cass环境下光标无显示
  7. begin tran,commit tran和rollback tran的用法
  8. 计算机主机后面的usb哪个不可接入,电脑的USB接口不能使用了怎么回事?主板usb接口全部失灵的解决方法...
  9. windows安装choco
  10. 鲸探发布点评:8月19日发售《小窗白云与凿山骨》数字藏品
  11. Axios 的简易学习笔记
  12. vivado与modelsim联合仿真遇到的问题2
  13. 前后端分离解决CSRF问题
  14. Nordic Thingy:52 SDK 安装及编译
  15. 车易加加油优惠卡_丰田Supra GRMN或2023年发布可 能搭载宝马3.0T发动机
  16. php 调用扫描仪,Mac_Mac怎么扫描文件?苹果电脑Mac使用扫描仪扫描文件教程,  当用户安装好扫描仪之后 - phpStudy...
  17. 第6篇 | Weblogic反序列化攻击不依赖日志溯源攻击时间
  18. 信息安全学习1. 基本概念及一些国家标准
  19. tensorflow Lite 2---- 移动端部署--yolov5+训练自己的数据集
  20. linux设置双屏强制设置分辨率,话说你们的双屏显示器是怎样设置的 尤其是外接显示器分辨率设置...

热门文章

  1. 东华|递归|青蛙跳台阶
  2. vscode 初始设置、基本操作及html的基本了解
  3. python读取txt为dataframe_python批量读取txt文件为DataFrame格式的方法总结
  4. 提醒事项默认列表怎么设置
  5. serve注解是加在哪个类_程序员笔试考试题和答案(java)
  6. Hibernate 之强大的HQL查询
  7. Java调用接口的原理
  8. FAT32转NTFS / NTFS转FAT32
  9. js 获取father_JavaScript中获取高度和宽度函数总结
  10. 有关计算机知识的英语论文,有关计算机英语论文范文