导航:首页 > 编程语言 > python多线程的问题

python多线程的问题

发布时间:2022-11-27 13:18:52

‘壹’ 为什么有人说 python 的多线程是鸡肋呢

首先,我并不认同这个观点,我觉得觉得Python 的多线程是鸡肋多余的人,应该还没有完全使用过Python 的多线程功能,并没有发掘它的潜在能力。

Python多线程最大的优点就是使用方便,很多时候我们并不需要做大量的密集型数据的处理运算,这时候用Python多线程是最方便快捷的,可以大大减少工作量、提高工作效率。

从以上几点我们就可以看出,Python多线程并不鸡肋,只是有时候使用者在不巧当的地方使用,它自然不是那么顺手,我们加深熟悉了解Python多线程的适用范围。

‘贰’ Python多线程是什么意思

几乎所有的操作系统都支持同时运行多个任务,一个任务通常就是一个程序,所有运行中的任务都对应一个进程。即当一个程序进入内存运行时,即变成一个进程。进程就是处于运行过程中的程序,并且具有一定的独立功能。进程是系统进行资源分配调度的一个独立单位,当一个程序运行时,内部可能包含多个顺序执流,每个顺序执行流就是一个线程。
1、线程在程序中是独立的,并发的执行流,划分尺度小于进程,所有多线程程序的并发性高;
2、进程在执行过程中拥有独立的内存单元,而多个线程共享内存,可以极大地提高进程程序的运行效率;
3、线程比进程具有更高的性能,由于同一个进程中的线程都有共性,多个线程共享同一个进程的虚拟空间,可以很容易实现通信。操作系统在创建进程中,必须为该进程分配独立内存空间,分配大量相关资源,但创建线程则简单得多。

‘叁’ Python多线程总结

在实际处理数据时,因系统内存有限,我们不可能一次把所有数据都导出进行操作,所以需要批量导出依次操作。为了加快运行,我们会采用多线程的方法进行数据处理, 以下为我总结的多线程批量处理数据的模板:

主要分为三大部分:


共分4部分对多线程的内容进行总结。

先为大家介绍线程的相关概念:

在飞车程序中,如果没有多线程,我们就不能一边听歌一边玩飞车,听歌与玩 游戏 不能并行;在使用多线程后,我们就可以在玩 游戏 的同时听背景音乐。在这个例子中启动飞车程序就是一个进程,玩 游戏 和听音乐是两个线程。

Python 提供了 threading 模块来实现多线程:

因为新建线程系统需要分配资源、终止线程系统需要回收资源,所以如果可以重用线程,则可以减去新建/终止的开销以提升性能。同时,使用线程池的语法比自己新建线程执行线程更加简洁。

Python 为我们提供了 ThreadPoolExecutor 来实现线程池,此线程池默认子线程守护。它的适应场景为突发性大量请求或需要大量线程完成任务,但实际任务处理时间较短。

其中 max_workers 为线程池中的线程个数,常用的遍历方法有 map 和 submit+as_completed 。根据业务场景的不同,若我们需要输出结果按遍历顺序返回,我们就用 map 方法,若想谁先完成就返回谁,我们就用 submit+as_complete 方法。

我们把一个时间段内只允许一个线程使用的资源称为临界资源,对临界资源的访问,必须互斥的进行。互斥,也称间接制约关系。线程互斥指当一个线程访问某临界资源时,另一个想要访问该临界资源的线程必须等待。当前访问临界资源的线程访问结束,释放该资源之后,另一个线程才能去访问临界资源。锁的功能就是实现线程互斥。

我把线程互斥比作厕所包间上大号的过程,因为包间里只有一个坑,所以只允许一个人进行大号。当第一个人要上厕所时,会将门上上锁,这时如果第二个人也想大号,那就必须等第一个人上完,将锁解开后才能进行,在这期间第二个人就只能在门外等着。这个过程与代码中使用锁的原理如出一辙,这里的坑就是临界资源。 Python 的 threading 模块引入了锁。 threading 模块提供了 Lock 类,它有如下方法加锁和释放锁:

我们会发现这个程序只会打印“第一道锁”,而且程序既没有终止,也没有继续运行。这是因为 Lock 锁在同一线程内第一次加锁之后还没有释放时,就进行了第二次 acquire 请求,导致无法执行 release ,所以锁永远无法释放,这就是死锁。如果我们使用 RLock 就能正常运行,不会发生死锁的状态。

在主线程中定义 Lock 锁,然后上锁,再创建一个子 线程t 运行 main 函数释放锁,结果正常输出,说明主线程上的锁,可由子线程解锁。

如果把上面的锁改为 RLock 则报错。在实际中设计程序时,我们会将每个功能分别封装成一个函数,每个函数中都可能会有临界区域,所以就需要用到 RLock 。

一句话总结就是 Lock 不能套娃, RLock 可以套娃; Lock 可以由其他线程中的锁进行操作, RLock 只能由本线程进行操作。

‘肆’ 为什么有人说 Python 的多线程是鸡肋

因为 Python 中臭名昭着的 GIL。

那么 GIL 是什么?为什么会有 GIL?多线程真的是鸡肋吗? GIL 可以去掉吗?带着这些问题,我们一起往下看,同时需要你有一点点耐心。

多线程是不是鸡肋,我们先做个实验,实验非常简单,就是将数字 “1亿” 递减,减到 0 程序就终止,这个任务如果我们使用单线程来执行,完成时间会是多少?使用多线程又会是多少?show me the code

那么把 GIL 去掉可行吗?

还真有人这么干多,但是结果令人失望,在1999年Greg Stein 和Mark Hammond 两位哥们就创建了一个去掉 GIL 的 Python 分支,在所有可变数据结构上把 GIL 替换为更为细粒度的锁。然而,做过了基准测试之后,去掉GIL的 Python 在单线程条件下执行效率将近慢了2倍。

Python之父表示:基于以上的考虑,去掉GIL没有太大的价值而不必花太多精力。

‘伍’ python 怎么实现多线程的

线程也就是轻量级的进程,多线程允许一次执行多个线程,Python是多线程语言,它有一个多线程包,GIL也就是全局解释器锁,以确保一次执行单个线程,一个线程保存GIL并在将其传递给下一个线程之前执行一些操作,也就产生了并行执行的错觉。

‘陆’ python多线程问题

a、b线程的执行顺序是由系统进行调度决定的。这种调度有很强的随机性。因此a、b线程谁先结束、谁后结束都是未知的。你可以运行以下程序,从而进一步的观察其中a、b线程的执行情况。

后结束的线程必然是20000。因为最终次数会达到20000。而另一个必然是一个小于等于19999的数。相差次数是系统调度决定,是随机的。并不存在“循环次数越大,相差就越大”的情况。你可以多试验几次试试。


importthreading
TOTAL=0
defmain():
MY_LOCK=threading.Lock()
classCountThread(threading.Thread):
def__init__(self,threadname):
threading.Thread.__init__(self)
self.threadname=threadname


defrun(self):
globalTOTAL
foriinrange(100):
MY_LOCK.acquire()
TOTAL=TOTAL+1
MY_LOCK.release()
print('%s:%s '%(self.threadname,TOTAL))
a=CountThread("a")
b=CountThread("b")
a.start()
b.start()

‘柒’ python 线程过多怎么处理

一般来说,多线程模式下,建议主线程只处理线程本身的调度,不去处理具体业务。通常在创建线程后,join等待所有线程退出。 就题主的问题,可以创建线程一、二之后,主线程等待线程一退出,之后用sys.exit退出。

‘捌’ 关于python多线程的一些问题。

  1. 创建的子线程默认是非守护的。

  2. 非守护:当主线程结束时,子线程继续运行,二者互不影响。

  3. 子线程是守护线程:当主线程结束时,子线程也结束(不管子线程工作有没有完成)。

  4. join作用是线程同步,是让主线程等待子线程结束才结束(主线程完成工作了也不结束,阻塞等待,等子线程完成其工作才一起结束)。

相信此时你已经懂你的两个问题了。

  1. 没加join的时候主线程结束了,所以命令提示符>>>就出来了,可是子线程还没结束,过了3/5秒后打印了字符串。加了join后主线程等两个子线程都结束才一起结束,所以最后才出来>>>。

  2. 理解确实有点偏差。守护是指子线程守护着主线程,你死我也死,谓之守护。

‘玖’ 有关python多线程的问题

Python的多线程只能解决非IO密集型问题,属于伪多线程,只能考虑多进程

‘拾’ Python多线程的一些问题

python提供了两个模块来实现多线程thread 和threading ,thread 有一些缺点,在threading 得到了弥补,为了不浪费你和时间,所以我们直接学习threading 就可以了。
继续对上面的例子进行改造,引入threadring来同时播放音乐和视频:
#coding=utf-8import threadingfrom time import ctime,sleepdef music(func): for i in range(2): print "I was listening to %s. %s" %(func,ctime())
sleep(1)def move(func): for i in range(2): print "I was at the %s! %s" %(func,ctime())
sleep(5)

threads = []
t1 = threading.Thread(target=music,args=(u'爱情买卖',))
threads.append(t1)
t2 = threading.Thread(target=move,args=(u'阿凡达',))
threads.append(t2)if __name__ == '__main__': for t in threads:
t.setDaemon(True)
t.start() print "all over %s" %ctime()

import threading
首先导入threading 模块,这是使用多线程的前提。

threads = []
t1 = threading.Thread(target=music,args=(u'爱情买卖',))
threads.append(t1)
创建了threads数组,创建线程t1,使用threading.Thread()方法,在这个方法中调用music方法target=music,args方法对music进行传参。 把创建好的线程t1装到threads数组中。
接着以同样的方式创建线程t2,并把t2也装到threads数组。

for t in threads:
t.setDaemon(True)
t.start()
最后通过for循环遍历数组。(数组被装载了t1和t2两个线程)

setDaemon()
setDaemon(True)将线程声明为守护线程,必须在start() 方法调用之前设置,如果不设置为守护线程程序会被无限挂起。子线程启动后,父线程也继续执行下去,当父线程执行完最后一条语句print "all over %s" %ctime()后,没有等待子线程,直接就退出了,同时子线程也一同结束。

start()
开始线程活动。

运行结果:
>>> ========================= RESTART ================================
>>> I was listening to 爱情买卖. Thu Apr 17 12:51:45 2014 I was at the 阿凡达! Thu Apr 17 12:51:45 2014 all over Thu Apr 17 12:51:45 2014

从执行结果来看,子线程(muisc 、move )和主线程(print "all over %s" %ctime())都是同一时间启动,但由于主线程执行完结束,所以导致子线程也终止。

继续调整程序:
...if __name__ == '__main__': for t in threads:
t.setDaemon(True)
t.start()

t.join() print "all over %s" %ctime()

我们只对上面的程序加了个join()方法,用于等待线程终止。join()的作用是,在子线程完成运行之前,这个子线程的父线程将一直被阻塞。
注意: join()方法的位置是在for循环外的,也就是说必须等待for循环里的两个进程都结束后,才去执行主进程。
运行结果:
>>> ========================= RESTART ================================
>>> I was listening to 爱情买卖. Thu Apr 17 13:04:11 2014 I was at the 阿凡达! Thu Apr 17 13:04:11 2014I was listening to 爱情买卖. Thu Apr 17 13:04:12 2014I was at the 阿凡达! Thu Apr 17 13:04:16 2014all over Thu Apr 17 13:04:21 2014

从执行结果可看到,music 和move 是同时启动的。
开始时间4分11秒,直到调用主进程为4分22秒,总耗时为10秒。从单线程时减少了2秒,我们可以把music的sleep()的时间调整为4秒。
...def music(func): for i in range(2): print "I was listening to %s. %s" %(func,ctime())
sleep(4)
...

子线程启动11分27秒,主线程运行11分37秒。
虽然music每首歌曲从1秒延长到了4 ,但通多程线的方式运行脚本,总的时间没变化。

阅读全文

与python多线程的问题相关的资料

热点内容
骁骑校全部小说顺序 浏览:394
如何将iphone手机照片转到安卓手机 浏览:31
从本地邮件到服务器是什么协议 浏览:226
外国片公交车男女主 浏览:234
瓦房店新玛特有电影院吗 浏览:933
免费观看网页版 浏览:622
叶子楣徐锦江演的电影 浏览:40
一级建造师法规pdf 浏览:496
phpshiro 浏览:161
无忧云服务器放行 浏览:634
免费最新大片观看网址 浏览:250
微信手势图标加密 浏览:746
存储服务器能干什么 浏览:785
c编辑软件怎么编译 浏览:597
hpc编译器论文 浏览:814
javac编译子目录下所有文件 浏览:430
卡友帮帮团是什么app 浏览:242
vnc启动命令 浏览:374
哺乳十电影 浏览:629
贵州java编译器 浏览:645