一、全局解释器锁(GIL)

  1、什么是全局解释器锁

      在同一个进程中只要有一个线程获取了全局解释器(cpu)的使用权限,那么其他的线程就必须等待该线程的全局解释器(cpu)使用权消失后才能使用全局解释器(cpu),即时多个线程直接不会相互影响在同一个进程下也只有一个线程使用cpu,这样的机制称为全局解释器锁(GIL)。

  2、全局解释器锁的好处

      1、避免了大量的加锁解锁的好处

      2、使数据更加安全,解决多线程间的数据完整性和状态同步

  3、全局解释器的缺点

      多核处理器退化成单核处理器,只能并发不能并行。

同一时刻的某个进程下的某个线程只能被一个cpu所处理,所以在GIL锁下的线程只能被并发,不能被并行。

实例:
import time
import threading def sub():
global num
num -= 1
time.sleep(1)
num = 100 # 定义一个全局变量
l = [] # 定义一个空列表,用来存放所有的列表
for i in range(100): # for循环100次
t = threading.Thread(target=sub) #每次循环开启一个线程
t.start() # 开启线程
l.append(t) # 将线程加入列表l
for i in l:
i.join() # 这里加上join保证所有的线程结束后才运行下面的代码
print(num)
# 输出结果为0

二、同步锁

  1、什么是同步锁?

    同一时刻的一个进程下的一个线程只能使用一个cpu,要确保这个线程下的程序在一段时间内被cpu执,那么就要用到同步锁。

  2、为什么用同步锁?

    因为有可能当一个线程在使用cpu时,该线程下的程序可能会遇到io操作,那么cpu就会切到别的线程上去,这样就有可能会影响到该程  序结果的完整性。

  3、怎么使用同步锁?

    只需要在对公共数据的操作前后加上上锁和释放锁的操作即可。

  4、实例:

import time
import threading R = threading.Lock() def sub():
global num
R.acquire() # 加锁,保证同一时刻只有一个线程可以修改数据
num -= 1
R.release() # 修改完成就可以解锁
time.sleep(1) num = 100 # 定义一个全局变量
l = [] # 定义一个空列表,用来存放所有的列表
for i in range(100): # for循环100次
t = threading.Thread(target=sub) # 每次循环开启一个线程
t.start() # 开启线程
l.append(t) # 将线程加入列表l
for i in l:
i.join() # 这里加上join保证所有的线程结束后才运行下面的代码
print(num)
# 输出结果为0

  5、扩展知识

    1、GIL的作用:多线程情况下必须存在资源的竞争,GIL是为了保证在解释器级别的线程唯一使用共享资源(cpu)。

    2、同步锁的作用:为了保证解释器级别下的自己编写的程序唯一使用共享资源产生了同步锁。

三、递归锁和死锁

  1、什么是死锁?

    指两个或两个以上的线程或进程在执行程序的过程中,因争夺资源而相互等待的一个现象

import time
import threading A = threading.Lock()
B = threading.Lock()
import threading class obj(threading.Thread):
def __init__(self):
super().__init__() def run(self):
self.a() # 如果两个锁同时被多个线程运行,就会出现死锁现象
self.b()
def a(self):
A.acquire()
print('')
B.acquire()
print(456)
time.sleep(1)
B.release()
print('qweqwe')
A.release()
def b(self):
B.acquire()
print('asdfaaa')
A.acquire()
print('(⊙o⊙)哦(⊙v⊙)嗯')
A.release()
B.release()
for i in range(2): # 循环两次,运行四个线程,第一个线程成功处理完数据,第二个和第三个就会出现死锁
t = obj()
t.start()

程序会出现阻塞现象

 2、什么是递归锁?

    在Python中为了支持同一个线程中多次请求同一资源,Python提供了可重入锁。这个RLock内部维护着一个Lock和一个counter

  变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获

  得资源。

import time
import threading A = threading.RLock() # 这里设置锁为递归锁
import threading class obj(threading.Thread):
def __init__(self):
super().__init__() def run(self):
self.a()
self.b() def a(self): # 递归锁,就是将多个锁的钥匙放到一起,要拿就全拿,要么一个都拿不到
# 以实现锁
A.acquire()
print('')
print(456)
time.sleep(1)
print('qweqwe')
A.release()
def b(self):
A.acquire()
print('asdfaaa')
print('(⊙o⊙)哦(⊙v⊙)嗯')
A.release()
for i in range(2):
t = obj()
t.start()

四、信号量(semaphore)

  1、什么是信号量?

    同进程的一样,semaphore管理一个内置的计数器,每当调用acquire()时内置函数-1,每当调用release()时内置函数+1。

   计数器不能为0,当计数器为0时acquire()将阻塞线程,直到其他线程调用release()。

import threading
import time mysf = threading.Semaphore(5) # 创建信号量对象,(5表示这个锁同时支持的个数) def func():
if mysf.acquire(): # 因为使用了信号量,下面的输出就会5个5个的同时输出
print(threading.currentThread().getName() + 'get semaphore')
time.sleep(1)
mysf.release()
for i in range(20):
t = threading.Thread(target=func)
t.start()

Python中的锁的更多相关文章

  1. 并发编程---线程 ;python中各种锁

    一,概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 --车间负责把资源整合到 ...

  2. python中的锁lock=threading.Lock()

    避免多个线程保卫同一块数据的时候,产生错误,所以加锁来防止这种问题 个人理解:当打印结果是交替打印时,但是如果需求是需要打印完一个线程的内容后,再去打印另一个线程的内容,就需要用到锁 不加锁打印结果: ...

  3. Python并发编程之谈谈线程中的“锁机制”(三)

    大家好,并发编程 进入第三篇. 今天我们来讲讲,线程里的锁机制. 本文目录 何为Lock( 锁 )?如何使用Lock( 锁 )?为何要使用锁?可重入锁(RLock)防止死锁的加锁机制饱受争议的GIL( ...

  4. python中的各种锁

    一.全局解释器锁(GIL) 1.什么是全局解释器锁 在同一个进程中只要有一个线程获取了全局解释器(cpu)的使用权限,那么其他的线程就必须等待该线程的全局解释器(cpu)使 用权消失后才能使用全局解释 ...

  5. python基础24 -----python中的各种锁

    一.全局解释器锁(GIL) 1.什么是全局解释器锁 在同一个进程中只要有一个线程获取了全局解释器(cpu)的使用权限,那么其他的线程就必须等待该线程的全局解释器(cpu)使 用权消失后才能使用全局解释 ...

  6. python学习笔记——多进程中的锁Lock

    1 进程锁 python编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性. 每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一线程访问对象. 在python中我 ...

  7. Python 中的进程与 锁

    理论知识 操作系统背景知识 顾名思义,进程即正在执行的一个过程.进程是对正在运行程序的一个抽象. 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一.操 ...

  8. 操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁

    并发编程前言: 1.网络应用 1)爬虫 直接应用并发编程: 2)网络框架 django flask tornado 源码-并发编程 3)socketserver 源码-并发编程 2.运维领域 1)自动 ...

  9. Python进阶(3)_进程与线程中的lock(线程中互斥锁、递归锁、信号量、Event对象、队列queue)

    1.同步锁 (Lock) 当全局资源(counter)被抢占的情况,问题产生的原因就是没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期.这种现象称为“线程不安全”.在开发过 ...

随机推荐

  1. Linux /etc/sudoers 文件详解

    [root@test ~]# cat /etc/sudoers## Sudoers allows particular users to run various commands as## the r ...

  2. RFB Net笔记

    ECCV2018 论文:Receptive Field Block Net for Accurate and Fast Object Detection 论文链接:https://arxiv.org/ ...

  3. __name__的意义与作用

    首先定义了一个test.py的文件,然后再定义一个函数,并在函数定义后直接运行: test.py def HaveFun():  if __name__ == '__main__':  print(' ...

  4. iOS制作自己的Framework框架

    1.新建工程选择iOS —> Cocoa Touch Framework 2.进入工程将工程自带的文件干掉 3.导入自己所需的文件 4.4.TARGETS —> Build Setting ...

  5. Java项目使用SQLite数据库后无法启动的问题

    背景: Java > maven 的 jar 项目 功能是记录用户的每天的按键次数 使用 jar2exe 工具将 jar 转为 exe 可执行文件 原本项目中使用的Mysql数据库,使用Myba ...

  6. docker 部署mvc项目 <四>

    一:部署方式 直接使用centos镜像,做一个镜像,此镜像制定端口号,在centos容器中安装jexus独立版,就可以了 docker run -d -p : -itd --name wds cent ...

  7. Java Spring Boot VS .NetCore (四)数据库操作 Spring Data JPA vs EFCore

    Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...

  8. 简单检测PHP运行效率脚本

    <?php $stratTime = microtime(true); $startMemory = memory_get_usage(); $a = 1; for($i = 1; $i < ...

  9. 关闭IIS开启自启

    关闭IIS开启自启 win+R输入services.msc 找到服务名称为World Wide Web Publishing Service 双击停止,右键禁用

  10. Java 常用知识点

    Java 常用知识点 1.日期格式化 SimpleDateFormat Date date=new Date(System.currentTimeMillis()) ; SimpleDateForma ...