首页 > 其他分享 >GIL锁,互斥锁

GIL锁,互斥锁

时间:2023-07-07 15:44:40浏览次数:38  
标签:解释器 多线程 Python counter 互斥 线程 GIL

一、GIL锁

1、全局解释器锁(Global Interpreter Lock,简称 GIL)

  GIL 是一种用于保护 Python 解释器在多线程环境下的数据完整性的机制。GIL 只存在是 CPython 解释器中,即官方的 Python 解释器实现

  GIL 是一个互斥锁,你可以使用多线程来并发处理任务,但在同一时刻只能有一个线程在执行 Python 字节码。

2、存在的背景

  GIL 的存在主要是因为 CPython 的内存管理机制(垃圾回收机制,python有一个垃回收线程)并不是线程安全的。

Python 中的对象引用计数机制(reference counting)是一种快速且高效的垃圾回收机制,但它对于多线程环境来说需要保证引用计数的一致性,这就需要 GIL 来确保同一时间只有一个线程能够访问和修改对象的引用计数。

由于 GIL 的存在,导致了 Python 在 CPU 密集型任务上的多线程性能并不理想。因为在这种情况下,即使使用了多个线程,由于 GIL 的限制,多个线程也不能真正并行执行,只能交替执行,因此无法充分利用多核 CPU 的优势。

然而,GIL 在 I/O 密集型任务上的影响较小。当线程执行 I/O 操作(如文件读写、网络请求)时,线程会主动释放 GIL,让其他线程有机会执行,从而提高了并发性能。

需要注意的是,GIL 只存在于 CPython 解释器中。其他一些 Python 解释器实现(如 Jython、IronPython)没有 GIL,它们可以更好地利用多线程并发执行。 

GIL 是 Python 解释器中的一种机制,用于保护解释器在多线程环境下的数据一致性。

虽然 GIL 限制了多线程的并行性能,但在 I/O 密集型任务中仍然可以提供一定的并发优势。

如果你需要在 Python 中处理 CPU 密集型任务,并发执行的需求较大,可以考虑使用多进程、异步编程或者使用其他 Python 解释器实现来绕过 GIL 的限制。

案例

创建了5个线程,每个线程都执行一个自增函数,该函数将一个全局计数器 counter 的值自增100万次。

由于 GIL 的限制,这段代码在多线程环境下并不能实现预期的并行效果。最终输出的计数器值通常会小于500万,而不是我们期望的500万(即每个线程自增100万次,共5个线程)。

这是因为 GIL 会确保在任何同一时间内只有一个线程在执行 Python 代码,导致多个线程无法同时访问和修改共享的计数器变量。没有抢到GIL锁的线程就会被释放掉。线程会交替地获取和释放 GIL,导致了部分线程的执行时间被浪费,没有执行。

import threading
import  time
# 全局变量
counter = 0

# 自增函数
def increment():
    global counter
    for i in range(1000000):
        counter += 1

# 创建并启动多个线程
threads = []
for i in range(5):
    thread = threading.Thread(target=increment)
    thread.start()
    threads.append(thread)

# 等待所有线程执行完成
for thread in threads:
    thread.join()

# 输出最终的计数器值
print("Final counter value:", counter)
# Final counter value: 2301450

二、互斥锁

1、

 

标签:解释器,多线程,Python,counter,互斥,线程,GIL
From: https://www.cnblogs.com/dgp-zjz/p/17535159.html

相关文章

  • 韦东山freeRTOS系列教程之【第四章】同步互斥与通信
    文章目录系列教程总目录概述4.1同步与互斥的概念4.2同步与互斥并不简单4.3各类方法的对比系列教程总目录本教程连载中,篇章会比较多,为方便同学们阅读,点击这里可以查看文章的目录列表,目录列表页面地址:javascript:void(0)概述本章是概述性的内容。可以把多任务系统当做一个团队,......
  • Linux多线程09-互斥锁
    为避免线程更新共享变量时出现问题,可以使用互斥量(mutex是mutualexclusion的缩写)来确保同时仅有一个线程可以访问某项共享资源。可以使用互斥量来保证对任意共享资源的原子访问。互斥量有两种状态:已锁定(locked)和未锁定(unlocked)。任何时候,至多只有一个线程可以锁定该互斥量。试......
  • Agile Notes
    -------------------------------------------------------------------------------------------------敏捷宣言我们一直在实践中探寻更好的软件开发方法,身体力行的同时也帮助他人。由此我们建立了如下(4个)价值观:1.个体和互动高于流程和工具2.工作的软件高于详尽的文档......
  • std::thread 二:互斥量(lock() & unlock())
     mutex 互斥量的作用是保护共享数据*:有lock() 就一定要有 unlock()#include<iostream>#include<thread>#include<mutex>#include<list>usingnamespacestd;classA{public:voidinNum(){for(inti=0;i<10000;i++)......
  • std::thread 二:互斥量(lock_guard())
    *:使用lock_guard后,就不可以使用lock()和unlock()*:lock_guard和智能指针一样,会自动解锁 #include<iostream>#include<thread>#include<mutex>#include<list>usingnamespacestd;classA{public:voidinNum(){for(inti=0;......
  • std::thread 二:互斥量(多个互斥量的解决方法)
     //*:这里的lock是函数模板,最少传两个互斥量//第一种,使用lock和unlockstd::mutexm_mutex1;std::mutexm_mutex2;std::lock(m_mutex1,m_mutex2);m_mutex1.unlock();m_mutex2.unlock();//第二种,使用lock和lock_guardstd::mutexm_mutex1;std::mutexm_m......
  • std::thread 二:互斥量(带超时的互斥量 timed_mutex())
     timed_mutex、 try_lock_for、 try_lock_until #include<iostream>#include<thread>#include<mutex>#include<list>usingnamespacestd;classA{public:voidinNum(){for(inti=0;i<10000;i++)......
  • Linux C 编程——互斥锁mutex
    1、多线程的问题引入多线程的最大的特点是资源的共享,但是,当多个线程同时去操作(同时去改变)一个临界资源时,会破坏临界资源。如利用多线程同时写一个文件:#include<stdio.h>#include<pthread.h>#include<malloc.h>constcharfilename[]="hello";void*thread(void*id){......
  • 什么时候只用互斥锁就可以,什么时候用条件变量+互斥锁
    互斥锁的作用是确保在同一时刻只有1个线程访问共享资源而条件变量的作用是,虽然某个线程加锁成功,可以访问共享资源了,但是这个时候如果某个条件没有变为true,那么这个线程也会被阻塞,直到其他线程调用notify_one来唤醒他,告诉他现在这个条件变为true了,他才可以访问共享资源。比如在生......
  • QT多线程(线程互斥)
    (文章目录)前言线程互斥是指在多线程并发执行时,为避免多个线程访问共享资源时发生冲突而采取的一种机制。本篇文章我们就这个问题来了解一下什么叫线程互斥,又如何解决线程互斥的问题。一、导致问题产生的原因和解决方法如果多个线程同时访问同一共享资源,可能会导致数据不一致......