美文网首页
python中的多线程

python中的多线程

作者: 东皇Amrzs | 来源:发表于2015-08-14 21:56 被阅读261次
balance = 0
    lock = threading.Lock()
    def run_thread(n):
        for i in range(100000):
        # 先要获取锁: 
        lock.acquire()
        try:
            # 放心地改吧: 
            change_it(n)
         finally:
             # 改完了一定要释放锁:
             lock.release()
  • 当多个线程同时执行lock.acquire()时,只有一个线程能成功地获取锁,然后继续执行代码,其他线程就继续等待直到获得锁为止。
    获得锁的线程用完后一定要释放锁,否则那些苦苦等待锁的线程将永远等待下去,成为死线程。所以我们用try...finally来确保锁一定会被释放。

  • 锁的好处就是确保了某段关键代码只能由一个线程从头到尾完整地执行,坏处当然也很多,首先是阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了。其次,由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁,导致多个线程全部挂起,既不能执行,也无法结束,只能靠操作系统强制终止

多核CPU

如果你不幸拥有一个多核CPU,你肯定在想,多核应该可以同时执行多个线程。
如果写一个死循环的话,会出现什么情况呢?
打开Mac OS X的Activity Monitor,或者Windows的Task Manager,都可以监控某个进程的CPU使用率。
我们可以监控到一个死循环线程会100%占用一个CPU。
如果有两个死循环线程,在多核CPU中,可以监控到会占用200%的CPU,也就是占用两个CPU核心。
要想把N核CPU的核心全部跑满,就必须启动N个死循环线程。
试试用Python写个死循环:

import threading, multiprocessing
def loop():
    x = 0
    while True:
         x = x ^ 1
        for i in range(multiprocessing.cpu_count()):
             t = threading.Thread(target=loop) 
             t.start()

可以看到!!启动与CPU核心数量相同的N个线程,在4核CPU上可以监控到CPU占用率仅有160%,也就是使用不到两核

即使启动100个线程,使用率也就170%左右,仍然不到两核。

但是用C、C++或Java来改写相同的死循环,直接可以把全部核心跑满,4核就跑到400%,8核就跑到800%,为什么Python不行呢?

因为Python的线程虽然是真正的线程,但解释器执行代码时,有一个GIL锁:Global Interpreter Lock,任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核

GIL是Python解释器设计的历史遗留问题,通常我们用的解释器是官方实现的CPython,要真正利用多核,除非重写一个不带GIL的解释器。

所以,在Python中,可以使用多线程,但不要指望能有效利用多核。如果一定要通过多线程利用多核,那只能通过C扩展来实现,不过这样就失去了Python简单易用的特点

不过,也不用过于担心,Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。(这里要比较一下得失了,是否非要使用线程,若是放弃线程使用进程有什么得失,廖老师在这里并没有提到)

小结

  1. 多线程编程,模型复杂,容易发生冲突,必须用锁加以隔离,同时,又要小心死锁的发生。

  2. Python解释器由于设计时有GIL全局锁,导致了多线程无法利用多核。多线程的并发在Python中就是一个美丽的梦。

相关文章

  • 线程、进程

    多线程 在介绍Python中的线程之前,先明确一个问题,Python中的多线程是假的多线程!为什么这么说,我们先明...

  • python爬虫--day05

    多线程 在介绍Python中的线程之前,先明确一个问题,Python中的多线程是假的多线程!为什么这么说,我们先明...

  • Python多线程编程——多线程编程中的加锁机制

    如果大家对Python中的多线程编程不是很了解,推荐大家阅读之前的两篇文章:Python多线程编程——多线程基础介...

  • 浅析python的GIL

    Python中的GIL锁 在Python中,可以通过多进程、多线程和多协程来实现多任务。 在多线程的实现过程中,为...

  • Python-线程、线程池

    1. Python多线程 python3中常用的线程模块为:_thread(Python2中的thread)、th...

  • GIL 全局解释器锁

    GIL面试题如下 描述Python GIL概念,以及它对Python多线程的影响?在一个多线程抓取网页的程序中,多...

  • Python多线程变量优化—threadLocal

    Python多线程变量优化—threadLocal 再多线程的环境下,每个线程都有自己的数据。在多线程编程中应该尽...

  • python爬虫--day06

    进程 进程的概念 python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python...

  • 07-多线程和协程

    在介绍Python中的线程之前,先明确一个问题,Python中的多线程是假的多线程!为什么这么说,我们先明确一个概...

  • 浅谈python中的多线程和多进程(二)

    原创:hxj7 本文继续分享一个关于python多线程和多进程区别的例子 前文《浅谈python中的多线程和多进程...

网友评论

      本文标题:python中的多线程

      本文链接:https://www.haomeiwen.com/subject/xdlwqttx.html