python GIL锁 锁 线程池 生产者消费模型

python的GIL 锁

  python内置的一个全局解释器锁 , 锁的作用就是保证同一时刻一个进程中只有一个线程可以被cpu调度

为什么有这把GIL锁?

  python语言的创始人在开发这门语言时 , 目的快速把语言开发出来 , 如果加上GIL锁(C语言加锁) , 切换时按照100条字节指令来进行线程间的切换

锁 :

  1.锁 : Lock(1次放1个)

    线程安全 , 多线程操作时 , 内部会让所有线程排队处理 , 如 : list / dict / Queue

    线程不安全 + 人  =>排队处理

    需求:

      a:创建100个进程 ,   在列表中追加8

      b:创建100个线程

        v = []

        锁

        把自己添加到列表中

        在读取列表的最后一个

        解锁

import threading
import time

v = []
lock = threading.Lock()

def func(arg):
    lock.acquire()
    v.append(arg)
    time.sleep(0.01)
    m = v[-1]
    print(arg,m)
    lock.release()

for i in range(10):
    t =threading.Thread(target=func,args=(i,))
    t.start()

  2.锁 : RLock(1次放1个)

import threading
import time

v = []
lock = threading.RLock()
def func(arg):
    lock.acquire()
    lock.acquire()

    v.append(arg)
    time.sleep(0.01)
    m = v[-1]
    print(arg,m)

    lock.release()
    lock.release()

for i in range(10):
    t =threading.Thread(target=func,args=(i,))
    t.start()

  3锁 : BoundedSemaphore (1次放N个) 信号量

import time
import threading

lock = threading.BoundedSemaphore(3)
def func(arg):
    lock.acquire()
    print(arg)
    time.sleep(1)
    lock.release()

for i in range(20):
    t =threading.Thread(target=func,args=(i,))
    t.start()

  4.锁 : Condition (1次方法x个)

import time
import threading

lock = threading.Condition()

def func(arg):
    print(‘线程进来了‘)
    lock.acquire()
    lock.wait() # 加锁

    print(arg)
    time.sleep(1)

    lock.release()

for i in range(10):
    t =threading.Thread(target=func,args=(i,))
    t.start()

while True:
    inp = int(input(‘>>>‘))

    lock.acquire()
    lock.notify(inp)
    lock.release()

  5.锁 : Event(1次放所有)

 

import time
import threading

lock = threading.Event()

def func(arg):
    print(‘线程来了‘)
    lock.wait() # 加锁:红灯
    print(arg)

for i in range(10):
    t =threading.Thread(target=func,args=(i,))
    t.start()

input(">>>>")
lock.set() # 绿灯

lock.clear() # 再次变红灯

for i in range(10):
    t =threading.Thread(target=func,args=(i,))
    t.start()

input(">>>>")
lock.set()

以上例子 :  线程安全 , 列表和字典线程安全

    为什么要加锁?

      非线程安全

      控制一段代码

6. threading.local

    作用 : 内部自动会为每个线程维护一个空间(字典) 用于当前存取属于自己的值 , 保证线程之间的数据隔离

      

      {
        线程ID: {...}
        线程ID: {...}
        线程ID: {...}
        线程ID: {...}
      }

import time
import threading

v = threading.local()

def func(arg):
    # 内部会为当前线程创建一个空间用于存储:phone=自己的值
    v.phone = arg
    time.sleep(2)
    print(v.phone,arg) # 去当前线程自己空间取值

for i in range(10):
    t =threading.Thread(target=func,args=(i,))
    t.start()

原理方法如下

import time
import threading

DATA_DICT = {}

def func(arg):
    ident = threading.get_ident()
    DATA_DICT[ident] = arg
    time.sleep(1)
    print(DATA_DICT[ident],arg)

for i in range(10):
    t =threading.Thread(target=func,args=(i,))
    t.start()

7. 线程池

from concurrent.futures import ThreadPoolExecutor
import time

def task(a1,a2):
    time.sleep(2)
    print(a1,a2)

# 创建了一个线程池(最多5个线程)
pool = ThreadPoolExecutor(5)

for i in range(40):
    # 去线程池中申请一个线程,让线程执行task函数。
    pool.submit(task,i,8)

8.生产者消费者模型

  三部件 :

      生产者

          队列 ,   先进先出

          扩展 : 栈  ,  后进先出

      消费者

  问 : 生产者消费者模型解决了啥问题?   不用一直等待问题

import time
import queue
import threading
q = queue.Queue() # 线程安全

def producer(id):
    """
    生产者
    :return:
    """
    while True:
        time.sleep(2)
        q.put(‘包子‘)
        print(‘厨师%s 生产了一个包子‘ %id )

for i in range(1,4):
    t = threading.Thread(target=producer,args=(i,))
    t.start()

def consumer(id):
    """
    消费者
    :return:
    """
    while True:
        time.sleep(1)
        v1 = q.get()
        print(‘顾客 %s 吃了一个包子‘ % id)

for i in range(1,3):
    t = threading.Thread(target=consumer,args=(i,))
    t.start()

锁  线程  线程池  threading.local  生成着消费者模型

概念性理解    配合代码

  

          

原文地址:https://www.cnblogs.com/SUIFAN/p/9629669.html

时间: 2024-11-05 06:27:42

python GIL锁 锁 线程池 生产者消费模型的相关文章

并发编程【四】锁和队列及生产者消费模型

1.锁multiprocessing-Lock 锁的应用场景:当多个进程需要操作同一个文件/数据的时候: 当多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题. 为保证数据的安全性,多进程中只有去操作一些进程之间可以共享的数据资源的时候才需要进行加锁: 枷锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务进行修改,即串行的修改,没错速度式慢了,但牺牲了速度却保证了数据的安全: 模拟查票抢票: import json import time from multiprocess

实现同步与互斥的一个实例--生产者消费模型

1.基础知识 1).生产者消费模型中存在3种关系: a.生产者与生产者之间是互斥的: b.消费者与消费者之间是互斥的: c.生产者与消费者之间是同步与互斥的: 2).生产者与消费者的场所,这儿我们选择单链表. 2.内容:多生产者生产一个结构体串在链表的表尾上,多消费者从表头取走结构体. 3.代码实现   1 #include<stdio.h>   2 #include<stdlib.h>   3 #include<pthread.h>   4    5 typedef 

python第三十七天,GIL全局解释器锁*****,线程池与进程池 同步异步,阻塞与非阻塞,异步回调

GIL全局解释器锁 1.什么是GIL 官方解释:'''In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe

线程锁、线程池

一.线程(IO密集型工作多线程有用) 线程: 概述: 若一个文件从上到下顺序执行,则为串行执行,整个py文件实际上是一个主线程 若多线程,则可以并行执行,同一个时刻可以运行多个代码段 给每个client请求分配一个线程,则这些线程可以同时工作 多线程.多进程: 1.一个应用程序,可以有多进程和多线程:默认是单进程.单线程 2.单进程.多线程 : 多线程:IO操作(输入输出流,文件操作)有用,因为几乎不用cpu来调度,一般用多线程来提高并发 计算型操作,需要用到cpu调度执行,一般用多进程提高并发

Day9 进程同步锁 进程队列 进程池 生产消费模型

进程同步锁: 当运行程序的时候,有可能你的程序同时开多个进程,开进程的时候会将多个执行结果打印出来,这样的话打印的信息都是错乱的,怎么保证打印信息是有序的呢? 其实也就是相当于让进程独享资源. 1 from multiprocessing import Process,Lock #引用函数 2 import time 3 def work(name,mutex): 4 mutex.acquire() #在这里加入锁 5 print('task <%s> is runing' %name) 6

Python练习【利用线程池爬取电影网站信息】

功能实现 爬取猫眼电影TOP100(http://maoyan.com/board/4?offset=90) 1). 爬取内容: 电影名称,主演, 上映时间,图片url地址保存到文件中; 2). 文件名为topMovie.csv; 3). 记录方式: 电影名称:主演:上映时间:图片url地址:评分; 4). 并爬取的信息保存在数据库中; 5). 使用多线程/线城池实现; 编程思路 1.利用多线程分配任务 2.编写单线程的任务实现功能 (1)获取指定url页面信息. (2)从指定信息中匹配所需的信

Python并发编程之线程池/进程池--concurrent.futures模块

h2 { color: #fff; background-color: #f7af0d; padding: 3px; margin: 10px 0px } 一.关于concurrent.futures模块 Python标准库为我们提供了threading和multiprocessing模块编写相应的多线程/多进程代码,但是当项目达到一定的规模,频繁创建/销毁进程或者线程是非常消耗资源的,这个时候我们就要编写自己的线程池/进程池,以空间换时间.但从Python3.2开始,标准库为我们提供了conc

Java 线程池 +生产者消费者+MySQL读取300 万条数据

1.1需求 数据库300 万条用户数据 ,遍历获取所有用户, 各种组合关联, 获取到一个新的json ,存到redis 上. 1.2 难点 数据库比较多, 不可能单线程查询所有的数据到内存. 1.3解决办法 多线程读取, 生产者 每次获取200 条数据, 消费者去消费.(这里 主要是根据MySQL分页去获取下一个200 条数据) 1.4 代码 1.4.1 调用方法 /** * 线程启动 */ public void update() { //redis操作类 HashRedisUtil redi

python(13)线程池:threading

先上代码: 1 pool = threadpool.ThreadPool(10) #建立线程池,控制线程数量为10 2 reqs = threadpool.makeRequests(get_title, data, print_result) #构建请求,get_title为要运行的函数,data为要多线程执行函数的参数 3 #最后这个print_result是可选的,是对前两个函数运行结果的操作 4 [pool.putRequest(req) for req in reqs] #多线程一块执行