Python之多线程

什么是线程?

要弄清楚线程的定义,往往就要和进程相互比较,从比较中才能更准确地明白一个东西的定义。首先有个数量关系是这样的,进程是由多线程组成的,每个进程起码都有一个线程
然后重点是有人说:

进程和线程简单而基本靠谱的定义如下:
1. 进程:程序的一次执行
2. 线程:CPU的基本调度单位

给一句话的定义,其实没有什么意思。但是,做为最根本的落脚点,放着也是极好的。
阮大神的这篇blog写的很通俗,但是不清楚,不深入,但是文章加评论却是相当有意思。

在我眼中的定义的理解

  • 进程:程序的一次执行?
    所谓程序的一次执行,就是指有自己的内存空间。就程序代码而言,就是当有全局变量,局部变量的时候,两者是不会互相影响的,每个进程都有自己独立的内存空间。其实,这些都是操作系统在影响着,你看,每个进程都有自己的内存空间,那么每个进程自己使用自己的东西的时候,就不会拿错东西,这样一来,我的程序员师叔们编程序的时候就不会弄错了,不用考虑这个变量是属于哪个进程这种问题了。(也不知道当时他们是不是这么想的:( )(那么问题来了,操作系统层是这样的,那么硬件层呢?CPU层到底是怎么实现的呢?)
  • 线程:CPU的基本调度单位?
    这个问题还没有考虑清楚,下次看看书,再来补充。有一个肤浅的一点就是在实际编程的过程中,全局变量是可以被所有线程所访问到的。(太肤浅了。。)

Python的多线程实现(Python3实现)

Python的标准库提供了两个模块:_threadthreading_thread是低级模块,threading是高级模块,对_thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块。
下面是廖大官网的例子,感觉非常不错,搬过来了哈。

import time, threading

# 假定这是你的银行存款:
balance = 0

def change_it(n):
    # 先存后取,结果应该为0:
    global balance
    balance = balance + n
    balance = balance - n

def run_thread(n):
    for i in range(100000):
        change_it(n)

t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)

如果是初次在学校中开始接触到线程的话,其实有一点是十分困惑的。(反正我是非常困惑的)就是有一种欲望是想看看threading这个模块的Thread函数的实现是什么?或者说就想弄清楚,弄明白run_thread,这个函数命传递进去了之后,程序代码到底做了什么?为什么要t1.start()t1.join()?就很奇怪,一个好好的函数,为什么要target传一个函数名,args参数传函数的参数,一起传不好吗?

然后当你真的点击去看实现的时候,就会一脸懵逼。那么如果控制这种想法呢?反正我就明白一点就是,学习的过程,并不是你前面的都明白的,下一个点也能明白的,有时候明白这种明白,知道这个点不是现阶段的问题这个事实是非常好的。

API中的几个注意点:

  1. target传递的是一个函数名,而不是函数调用,如果你看过Python的线程的API的话,也是要注意这一点的。
  2. balance这种全局变量是可以被所有线程访问到的。然后就有了锁的概念,那不是另一个世界了。
  3. 线程的start()join()函数的作用,线程的调度是由操作系统决定的,没有先后顺序,高级语言的有些一条语句其实可以拆分之类的概念,这里是不会提的,不然显得没重点,可以看一下廖大的教程,很详细。
  4. 下面是其中一种运行结果。
初始值 balance = 0

t1: x1 = balance + 5  # x1 = 0 + 5 = 5

t2: x2 = balance + 8  # x2 = 0 + 8 = 8
t2: balance = x2      # balance = 8

t1: balance = x1      # balance = 5
t1: x1 = balance - 5  # x1 = 5 - 5 = 0
t1: balance = x1      # balance = 0

t2: x2 = balance - 8  # x2 = 0 - 8 = -8
t2: balance = x2   # balance = -8

结果 balance = -8
  • 线程中锁。
balance = 0
lock = threading.Lock()

def run_thread(n):
    for i in range(100000):
        # 先要获取锁:
        lock.acquire()
        try:
            # 放心地改吧:
            change_it(n)
        finally:
            # 改完了一定要释放锁:
            lock.release()

还真是,这个API比JAVA中的要简单很多。

  • 还有一种是一个python的类继承的thread的API还没有写,下次补充。显示这个继承的API不好,类中参杂了很多不是这个类的东西。

GIL

GIL是全局解释器锁,可以看这个东西的英文比较能懂。因为这个东西的存在,Python的多线程,不论怎么样都只能充分使用CPU的一个核心。有下面几点要注意:

  1. Python是一种语言,语言也可以理解为一种语法标准,在这个标准里面是没有GIL的,但是这个语言的实现,官方的解释去CPython中是用了GIL来实现的,但是比如JPython是没有这个概念的。(那么问题来了,为什么还是有那么多人使用CPython?)
  2. Python3中的GIL也是一样存在的,只是Python3中对GIL的一个多线程比单线程还要慢的这一个问题进行了修复,没有从根本上解决这个问题。
  3. 想充分利用多核CPU的话,可以使用多进程。(那么为什么多进程可以避开GIL而充分使用CPU呢?)

最后之前

为什么多线程或者说多进程会比单进程快呢?对于IO密集型,计算密集型?可以从CPU和操作系统的角度来谈谈这个问题吗?计算机有几个IO方式呢,比如DMA是什么,有什么不同?计算机IO的时候,是需要CPU的运行吗?需要吗?不需要吗?不需要的话,又是谁把磁盘中的数据读到内存中的呢?除了CPU还有谁有这个能力呢?线程和进程在CPU这个层面到底是什么瓜葛呢?待我好好看书,来回答这个问题。

最后

写给未来的自己,也写给读到最后的你,能力有限,如有错误,请交流谈论及指正,如果有帮助,请评论或者点击喜欢,谢谢。

参考:

进程与线程的一个简单解释
廖雪峰的官方教程之多线程
Python 之父谈 Python
Python 3.2与更好的GIL

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • 线程 引言&动机 考虑一下这个场景,我们有10000条数据需要处理,处理每条数据需要花费1秒,但读取数据只需要0....
    不浪漫的浪漫_ea03阅读 357评论 0 0
  • 引言&动机 考虑一下这个场景,我们有10000条数据需要处理,处理每条数据需要花费1秒,但读取数据只需要0.1秒,...
    chen_000阅读 501评论 0 0
  • 光有“四勿”还不够 有人提出以孔子提倡的“四勿”来净化当今的社会风气,我认为仅仅如此并不能收到理想的效果。 孔子云...
    二班班阅读 279评论 0 0
  • 有双儿女万事足 早晨上班的公交车上,一中年男士上车,“两个小朋友”,中年男士刷完卡,又投了两枚硬币到公交车的投币箱...
    赤北阅读 722评论 0 0
  • 我个人喜欢朱传奇的素描起稿,什么?你问我原因?我擦,装逼呗。调子和明暗和形同时出。这种考生在考场其实足够把人唬住...
    写不出爱你的笔阅读 552评论 12 9