Python中多线程的阻塞问题
在使用Queue模块+多线程模拟生产者+消费者问题时,遇到了一个小问题,现在记录下来。供可能会遇到类似问题的初学者们参考。
该问题的完整参考代码如下。主要实现了以下的功能:在一个线程中,开启生产者模式,生成出来的object会put进一个Queue对象queue中。除此以外,在n个线程中(本代码中n为5,nfuncs = 5),开启消费者模式,每一个消费者线程会在一个while循环中不断地从queue中消耗一个object(使用get方法),直到生产者生产出的object被全部消耗(本代码中设为100个object)。
from random import randint
from time import sleep
from Queue import Queue
from threading import Thread,Lock,currentThread
lock = Lock()
def writes(queue):
print "producing object for Q...",
queue.put('xxx', 1)
print "size now", queue.qsize()
def readQ(queue):
val = queue.get(1)
print "consumed object from Q... size now", \
queue.qsize()
print currentThread().name
def writer(queue, loops):
for i in range(loops):
lock.acquire()
writes(queue)
lock.release()
sleep(0.1)
def read(queue):
while queue.qsize() >0 :
sleep(randint(2, 4))
lock.acquire()
readQ(queue)
lock.release()
funcs = [writer, read]
nfuncs = range(5)
def main():
nloops1 = 100
q = Queue(1024)
thread = []
t = Thread(target = writer, args = (q, nloops1))
thread.append(t)
for i in nfuncs:
t = Thread(target = read, args = (q,))
thread.append(t)
for i in range(len(thread)):
thread[i].start()
for i in range(len(thread)):
thread[i].join()
print "All Done"
if __name__ == '__main__':
main()
为了防止生产速度跟不上消费的速度,生产线程中每次生产仅间隔0.1秒,且在消费线程中每次消费之前,随机sleep 2~3秒。
在运行之后,生产的object数量达到100(实际不会print 100号object的生成,因为在生产的过程中已经开始消费),然后多个线程开始消费。然而在把object数量消费至0以后,线程们并不会结束,既“print “”All done“””语句一直没有被执行。
思考以后,得出了三种解决途径:
1.在线程的Join方法中加入参数timeout,如果线程阻塞,线程运行时间达到timeout时,将中止该线程。
该方法的缺点在于当生产数量不确定时,timeout的时间无法很好的确定。如果join的时间太短,可能有的进程还在运行,主进程就继续运行了。如果join的时间太长,在线程很多的情况下,将会阻塞很长的一段时间。
2.试图考虑为什么线程会阻塞。
发现在read函数中,如前所述,在每次消费之前,随机sleep 2~3秒。于是可能会出现以下的问题。
当 queue.qsize() = 1的时候,某个线程x进入了while循环,然后开始睡眠2~3秒,在这个睡眠过程中,GUI切换至其它的线程,此时由于线程x处于睡眠,并没有调用readq函数,因此queue中仍然有一个元素。以此类推,每个进程都在queue.qsize() = 1时进入了while循环,然后最早结束睡眠的线程将调用readq函数中的queue.get(1)。之后其它进程在调用queue.get(1)时,将会因为queue中缺少元素阻塞。
解决方法如下:
def read(queue):
sleep(randint(2, 4))
while queue.qsize():
lock.acquire()
readQ(queue)
lock.release()
sleep(randint(2, 4))
在while之前睡眠,且将每次消费时所需的睡眠放至readQ函数之后。可避免多个线程同时进入while循环,该改进将不会
引起阻塞。
3.Queue中的get方法,若将其参数设置为非0,则不会因为队列中没有可用元素而阻塞。将get的参数设置为0,
利用try/excep语句,当get不到数据引起异常时,excep一个break,中断线程。
Python中多线程的阻塞问题的更多相关文章
- 通过编写聊天程序来熟悉python中多线程及socket的用法
1.引言 Python中提供了丰富的开源库,方便开发者快速就搭建好自己所需要的应用程序.本文通过编写基于tcp/ip协议的通信程序来熟悉python中socket以及多线程的使用. 2.python中 ...
- Python 中多线程之 _thread
_thread模块是python 中多线程操作的一种模块方式,主要的原理是派生出多线程,然后给线程加锁,当线程结束的 时候取消锁,然后执行主程序 thread 模块和锁对象的说明 start_new_ ...
- python中多线程相关
基础知识 进程:进程就是一个程序在一个数据集上的一次动态执行过程 数据集:程序执行过程中需要的资源 进程控制块:完成状态保存的单元 线程:线程是寄托在进程之上,为了提高系统的并发性 线程是进程的实体 ...
- Python中多线程与多进程的恩恩怨怨
概念: 并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运 ...
- Python 中多线程共享全局变量的问题
写在前面不得不看的一些P话: Python 中多个线程之间是可以共享全局变量的数据的. 但是,多线程共享全局变量是会出问题的. 假设两个线程 t1 和 t2 都要对全局变量g_num (默认是0)进行 ...
- python中多线程
多线程 什么是多线程 开启线程的两种方式 进程和线程的区别 Thread对象的其他属性和方法 守护线程 死锁现象与递归锁 信号量.Event定时器 线程Queue 进程池和线程池 什么是多线程 在传统 ...
- python中多线程,多进程,多协程概念及编程上的应用
1, 多线程 线程是进程的一个实体,是CPU进行调度的最小单位,他是比进程更小能独立运行的基本单位. 线程基本不拥有系统资源,只占用一点运行中的资源(如程序计数器,一组寄存器和栈),但是它可以与同属于 ...
- python中多线程(1)
一多线程的概念介绍 threading模块介绍 threading模块和multiprocessing模块在使用层面,有很大的相似性. 二.开启多线程的两种方式 1.创建线程的开销比创建进程的开销小, ...
- python中多线程,多进程,队列笔记(一)
threading简介:If you want your application to make better use of the computational resources of multi- ...
随机推荐
- 洛谷 P1886 滑动窗口(单调队列)
题目链接 https://www.luogu.org/problemnew/show/P1886 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始 ...
- python------生产者消费者模型 和 管道
一.为什么要使用生产者和消费者? 在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程,在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才 ...
- cocos2d-x 3.0正式版创建project笔记
cocos2d-x 3.0正式版创建project笔记 不知道Beta版那个高大上的对话框哪里去鸟,正式版又回归到命令行,不知道触碰如此频繁的玩弄追随者的编程习惯是出于什么心理,假设不是为了这 ...
- 安装weblogic界面安装
如果中间有任何问题请联系作者:291562721 界面安装weblogic首先 需要工具: 链接:https://pan.baidu.com/s/1x3uYxsnycjT2Xi2TOTbDdQ 提取码 ...
- CSS世界中的“盒子”
1.块级元素 HTML标签通常被分为两类:块级元素和内联元素. “块级元素”和“display为block的元素”不是同一个概念.例如<li>元素默认的display值为list-item ...
- elasticsearch 基础 —— Common Terms Query常用术语查询
常用术语查询 该common术语查询是一个现代的替代提高了精确度和搜索结果的召回(采取禁用词进去),在不牺牲性能的禁用词. 问题 查询中的每个术语都有成本.搜索"The brown fox& ...
- windows10安装nodejs 10和express 4
最进做一个个人博客系统,前端用到了semanticUI,但是要使用npm工具包,所以需要安装nodejs,nodejs自带npm 下载 去官网下载自己系统对应的版本,我的是windows:下载 可以在 ...
- Codeforces Round #538 (Div. 2) (CF1114)
Codeforces Round #538 (Div. 2) (CF1114) 今天昨天晚上的cf打的非常惨(仅代表淮中最低水平 先是一路缓慢地才A掉B,C,然后就开始杠D.于是写出了一个O( ...
- apache You don't have permission to access / on this server.无权访问
环境:ubuntu16.4 apache2 原因:修改了apache web项目路径 解决: 1. 修改 /etc/apache2/sites-available/000-default.conf 文 ...
- RandomAccessFile类学习
RandomAccessFile类学习 RandomAccessFile是io包的类,从Object直接继承而来,只可以对文件进行操作,可以对文件进行读取和写入. 当模式为r:当文件不存在时会报异常: ...