了解信号量Semaphore和线程池的差异

信号量

  其实本质上是锁,Lock是单锁,信号量是指定多把锁,也就是说通过信号量指定多个数线程可以访问相同资源,一般情况下读操作可以有多个,但写操作同时只有一个

信号量模块  semaphore

  # 使用起来和普通锁没 什么区别,但这个是比锁更加粗粒度锁,锁的是线程

  # 在线程实例前加锁,把锁传递进线程,在线程结束时候释放锁


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

from threading import Thread, Semaphore

from queue import Queue

def add(chan, sem_lock):

    for in range(10):

        chan.put(i)

    # 释放锁

    sem_lock.release()

if __name__ == ‘__main__‘:

    numbers = Queue()

    # 申明信号量

    sem_lock = Semaphore(4)

    sem_lock.acquire()

    # 把锁传递进线程

    tasks = {Thread(target=add, args=(numbers, sem_lock), name="北门吹雪 %s" % i) for in range(10)}

    for task in tasks:

        task.start()

    for task in tasks:

        task.join()

    print(numbers.get())

  

线程池

  不仅仅是数量控制,可以获取线程状态、任务状态、线程返回值等信息

  线程池模块  ThreadPollExecutor

线程池使用过程

  1. 实例化线程池

  2. 提交任务,会有个返回对象,submit是不会堵塞,立即返回

  3. 让主线程等待线程执行完成

  4. 关闭线程池

获取状态信息  线程对象

  1. 判断是否执行完        .done()

  2. 获取任务执行结果,堵塞    .result()

  3. 取消任务            .cancle()

对多个线程列表获取结果  线程对象

  1. as_complated        获取已经执行完成的线程结果


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

def add(number, name):

    sum = 0

    for in range(number):

        sum += i

    # 模拟个线程执行堵塞情况

    time.sleep(random())

    # 返回线程执行结果

    return sum

if __name__ == ‘__main__‘:

    thread_pool = ThreadPoolExecutor(max_workers=3)

    print("北门吹雪:http://www.cnblogs.com/2bjiujiu/")

    name = "北门吹雪"

    tasks = {thread_pool.submit(add, randint(1020), name) for in range(20)}

    # map方法和as_completed最大区别在于map变化的只是参数线程是同一个线程,而as_completed可以执行不同的线程任务

    for data in thread_pool.map(add, {randint(1020for in range(20)}):

        print(data)

  2. map            直接返回线程执行结果,保持传递进去顺序


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

def add(number):

    sum = 0

    for in range(number):

        sum += i

    # 模拟个线程执行堵塞情况

    time.sleep(random())

    # 返回线程执行结果

    return sum

if __name__ == ‘__main__‘:

    print("北门吹雪")

    thread_pool = ThreadPoolExecutor(max_workers=3)

    tasks = {thread_pool.submit(add, randint(1020)) for in range(20)}

    # map方法和as_completed最大区别在于map变化的只是参数线程是同一个线程,而as_completed可以执行不同的线程任务

    for data in thread_pool.map(add, {randint(1020for in range(20)}):

        print(data)

  3. wait          等待所有线程执行完成


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

from concurrent.futures import ThreadPoolExecutor, as_completed, wait

from random import randint, random

import time

def add(number):

    sum = 0

    for in range(number):

        sum += i

    # 模拟个线程执行堵塞情况

    time.sleep(random())

    # 返回线程执行结果

    return sum

if __name__ == ‘__main__‘:

    thread_pool = ThreadPoolExecutor(max_workers=3)

    tasks = {thread_pool.submit(add, randint(1020)) for in range(20)}    print("北门吹雪")

    # 主线程等待所有子线程执行完,不需要结果

    # wait(tasks)


1

<span style="font-family: ‘Microsoft YaHei‘;">北门吹雪:http://www.cnblogs.com/2bjiujiu/</span>

经验:

  1. 线程池和信号量在某种程度如允许执行的线程数效果上是一样,但线程池可以获取线程执行结果得到线程执行状态

  2. 使用线程池需要首先实例化,然后提交线程,返回线程对象,然后在主线程中选择获取结果或者不需要结果,也可以选择堵塞等待线程执行完或不等待线程执行完

  3. 获取线程执行结果,可以参照Go语言中CSP通信模式,个人觉得这是个非常好的解决方案,这样的线程池接口提交远比CSP通信来的复杂

原文地址:https://www.cnblogs.com/LucasSong/p/12262879.html

时间: 2024-11-07 04:38:24

了解信号量Semaphore和线程池的差异的相关文章

python基础 信号量 semaphore evevt 线程queue 生产者消费者模型

线程锁相当于同时只能有一个线程申请锁,有的场景无数据修改互斥要求可以同时让多个线程同时运行,且需要限制并发线程数量时可以使用信号量 1 import threading, time, queue 2 3 def test(name): 4 semaphore.acquire() #获取信号量锁 5 print('my name is %s' %name) 6 time.sleep(1) 7 semaphore.release() #释放信号量锁 8 9 semaphore = threading

java 信号量Semaphore

在很多情况下,可能有多个线程需要访问数目很少的资源.假想在服务器上运行着若干个回答客户端请求的线程.这些线程需要连接到同一数据库,但任一时刻 只能获得一定数目的数据库连接.你要怎样才能够有效地将这些固定数目的数据库连接分配给大量的线程? 答:1.给方法加同步锁,保证同一时刻只能有一个人去调用此方法,其他所有线程排队等待,但是此种情况下即使你的数据库链接有10个,也始终只有一个处于使 用状态.这样将会大大的浪费系统资源,而且系统的运行效率非常的低下. 2.另外一种方法当然是使用信号量,通过信号量许

Android线程池详解

直接使用线程 在Android开发的时候,当我们需要完成一个耗时操作的时候,通常会新建一个子线程出来,例如如下代码 new Thread(new Runnable() { @Override public void run() { //耗时代码 } }).start(); 这种方式的线程随处可见,但是这种方式的写法是存在一定问题的,我们知道,在操作系统中,线程是操作系统调度的最小单元,同时线程又不能无限制的产生,并且线程的创建和销毁都会有资源的开销,同时当线程频繁的创建或者销毁的时候,还会让GC

Java多线程与并发库高级应用之信号量Semaphore

JDK1.5提供了一个计数信号量Semaphore类.Semaphore 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目,并提供了同步机制. Semaphore提供了两个构造器来创建对象: 1)Semaphore(int permits):创建具有给定的许可数和非公平的公平设置的Semaphore. 2)Semaphore(int permits, boolean fair):创建具有给定的许可数和给定的公平设置的Semaphore.如果此信号量保证在争用时按先进先出的顺序授予许可,则为

java笔记--对信号量Semaphore的理解与运用

java Semaphore 信号量的使用: 在java中,提供了信号量Semaphore的支持. Semaphore类是一个计数信号量,必须由获取它的线程释放, 通常用于限制可以访问某些资源(物理或逻辑的)线程数目. 一个信号量有且仅有3种操作,且它们全部是原子的:初始化.增加和减少 增加可以为一个进程解除阻塞: 减少可以让一个进程进入阻塞. --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3910406.html "谢谢-- 信

基于C++11的线程池,简洁且可以带任意多的参数

咳咳.C++11 加入了线程库,从此告别了标准库不支持并发的历史.然而 c++ 对于多线程的支持还是比较低级,稍微高级一点的用法都需要自己去实现,譬如线程池.信号量等.线程池(thread pool)这个东西,在面试上多次被问到,一般的回答都是:"管理一个任务队列,一个线程队列,然后每次取一个任务分配给一个线程去做,循环往复." 貌似没有问题吧.但是写起程序来的时候就出问题了. 废话不多说,先上实现,然后再啰嗦.(dont talk, show me ur code !) 代码实现 1

c++11线程池实现

咳咳.c++11 加入了线程库,从此告别了标准库不支持并发的历史.然而 c++ 对于多线程的支持还是比较低级,稍微高级一点的用法都需要自己去实现,譬如线程池.信号量等.线程池(thread pool)这个东西,在面试上多次被问到,一般的回答都是:"管理一个任务队列,一个线程队列,然后每次取一个任务分配给一个线程去做,循环往复." 貌似没有问题吧.但是写起程序来的时候就出问题了. 废话不多说,先上实现,然后再啰嗦.(dont talk, show me ur code !) #ifnde

13 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件  queue队列 生产者消费者模型 Queue队列 开发一个线程池

本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Queue队列 开发一个线程池 进程 语法 进程间通讯 进程池 操作系统发展史 手工操作(无操作系统) 1946年第一台计算机诞生--20世纪50年代中期,还未出现操作系统,计算机工作采用手工操作方式. 手工操作程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入输入机,然后启动输入机把

秒杀多线程第八篇 经典线程同步 信号量Semaphore (续)

java semaphore实现: Semaphore当前在多线程环境下被扩放使用,操作系统的信号量是个很重要的概念,在进程控制方面都有应用.Java 并发库 的Semaphore 可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可.比如在Windows下可以设置共享文件的最大客户端访问个数. package com.multithread.semaphore; import