V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
lovepython
V2EX  ›  Python

到底是什么多线程?函数内的变量, 类里变量,实例对象属性 ,模块变量等,多线程是怎么控制的,实在不会描述,请看正文里例子,求高手帮解答。

  •  
  •   lovepython · 2016-01-18 12:58:48 +08:00 · 2474 次点击
    这是一个创建于 2993 天前的主题,其中的信息可能已经有所发展或是发生改变。

    注:数字代表行号
    然后本人非计算机出身,如果问题太水,还请各位见谅

    1 class CreateListThread(Thread):
    2 def run(self):
    3 entries = []
    4 for i in range(30):
    5 entries.append(i)
    6 print(entries)
    7
    8
    9 def use_create_list_thread():
    10 for i in range(3):
    11 t = CreateListThread()
    12 t.start()
    13 use_create_list_thread()

    书上说线程是 cpu 执行的最小单位,线程本身不能控制自己的执行时间长短

    我的理解-代码里的每句话和它的上一句,下一句都有可能不是在同一线程下执行,因为不确定什么时候就执行了其他线程。

    第一个疑问
    上面的代码,创建了三个线程类,是不是可以这么理解:线程运行到 3 ,突然中断,运行到 4 时是另一个线程,或者线程运行到 3 ,也运行到 4 ,运行到 5 时切换到了其他线程。不知道这么理解对吗?

    第二个疑问
    还是上面的代码,针对第一个疑问的疑问。
    一个线程运行到 3 ,突然切换到另一个线程,这个线程是不是从 4 开始运行,还是从 2 开始。

    第二个疑问
    上面代码 3 的地方,是一个变量。虽然代码只有一份,也就是那一句话。
    假设一个线程运行到 5 ,此时 entries 是[0],如果这时,切换到另一个线程,假设这个线程刚启动,那这个 entries 的值是什么?

    如果是个[],是不是可以这么理解: entries 虽然代码只有一句,实际上每个线程都拥有各自的 entries ,操作 entries 时,并不影响他的值。

    14 条回复    2016-01-21 14:31:01 +08:00
    xiaoshenke
        1
    xiaoshenke  
       2016-01-18 14:14:38 +08:00 via Android
    你可以把主线程想象成你老师 你老师要干活的时候把活分给了你们班班委 班委之间是独立的
    bluefalconjun
        2
    bluefalconjun  
       2016-01-18 14:26:13 +08:00
    作为技术薄弱的老油条.. 看到这个问题也是比较纠结的... 不知道怎么回答才能帮助到你.

    代码的每一句话->编译完成后会变成汇编代码->在指定 cpu 上运行时, 只有汇编级别的原子操作才不会被切换(这句话不知道对不对,我猜的).

    既然有线程切换,那一定有操作系统支持, PCB 啊之类, 它会保证每个 Entires 里面的值, 是按照当前线程的值来处理的(处理 /恢复现场).

    由于不理解你的 sample code 的语境(话说这是什么语言? ), 你的三个疑问, 回答不了.

    用比较熟的 c 语言来解释下线程的样子(说错了请轻拍):

    volatile int kIcount = 0;

    void one_job(void) {
    int i =0;
    for(i=0;i<20;i++) {
    printf("i=%d\n",i);
    kIcount++;
    printf("global kIcount = %d", kIcount);
    }
    return;
    }

    int main(int argc, char** argv) {

    pthread_create(thread1,x,(void*)one_job(),x,x);
    pthread_create(thread2,x,(void*)one_job(),x,x);

    //wait all thread runtime quit.
    while(1) { /xx}
    return;
    }

    以上代码中, 单个函数里面 i 的打印一定是交替连续的, 因为线程切换会保存现场, kIcount 的打印两边加到一起一定是连续的, 因为每次打印时会去取 kIcount 的值. 可能的打印结果.
    i=0 //thread1
    global kIcount = 0 //thread1
    i=0 //thread2
    global kIcount = 1 //thread2
    i=1 //thread1
    global kIcount = 2 //thread1

    以上...
    lovepython
        3
    lovepython  
    OP
       2016-01-18 14:36:11 +08:00
    @bluefalconjun 我的是 python 语言
    lovepython
        4
    lovepython  
    OP
       2016-01-18 14:37:05 +08:00
    @xiaoshenke 能针对我的三个疑问回答吗
    bluefalconjun
        5
    bluefalconjun  
       2016-01-18 14:37:22 +08:00
    @lovepython 发现了 ... 看来还是反应迟钝...
    lovepython
        6
    lovepython  
    OP
       2016-01-18 14:57:59 +08:00
    @bluefalconjun 你的 c 那个代码 kIcount 是全局的,两个线程操作,最后值能正确吗?函数里 int i,是不是每个线程都有一个这个 i,虽然代码是一份?即使中间执行到某个地方中断了,下次这个线程也会知道 i 的具体指。
    bluefalconjun
        7
    bluefalconjun  
       2016-01-18 15:02:56 +08:00
    @lovepython :
    kIcount 全局 两个线程操作 值是正确的. 因为是 volatile 定义.
    i 是有两份, 因为是局部变量, 中断后恢复现场时 i 的值是会被记录的.
    xiaoshenke
        8
    xiaoshenke  
       2016-01-18 16:21:15 +08:00 via Android
    每种系统里的线程语义是不一样的 你心中只要有一个大概运行的模型 就能很容易理解了 如果连线程到底是什么都不懂 就会越来越晕 多跑几个例子就懂了 别老看书
    lovepython
        9
    lovepython  
    OP
       2016-01-18 16:29:13 +08:00
    @xiaoshenke 什么叫大概模型啊,你说的举例我当然懂,问题得落实到代码上啊。
    wizardforcel
        10
    wizardforcel  
       2016-01-18 17:01:47 +08:00 via Android
    线程的调度是由 os 控制的,你可以认为线程的执行顺序完全随机,会在每条原子指令执行后切换。保证原子性的办法就是加锁,或者使用原子操作库。对执行顺序不要做任何假设,保证顺序条件量的办法是条件量。
    wizardforcel
        11
    wizardforcel  
       2016-01-18 17:02:28 +08:00 via Android
    @wizardforcel 保证执行顺序的办法就是使用条件量。
    lovepython
        12
    lovepython  
    OP
       2016-01-18 17:34:05 +08:00
    @wizardforcel 如果不做限制,也是就是线程的执行顺序随机,一个线程都执行半天了,可能另一个还没启动。

    那这样,就应该是,一个线程执行到 3 ,有可能另一个线程从 2 刚开始执行,也有可能从 4 执行(比刚才那个线程启动得早,正好到 4 ,切换了)


    这么理解对吧?
    hitmanx
        13
    hitmanx  
       2016-01-21 13:25:32 +08:00
    你这个问题并不是 python 的问题,而是关于操作系统基础课里的问题.比如线程共享哪些变量,线程自己拥有什么变量,什么是原子操作,什么是锁\信号量,它在操作系统里是怎么实现的,线程是怎么调度的,这些抓起一本操作系统的书,都会很详细地和你解释,估计也就几十页,100 页,系统地看一下也不费多少时间

    书的话我推荐<现代操作系统>, 视频教程我推荐哈工大孙志岗老师的"操作系统"公开课和网易公开课中斯坦福的<编程范式>.都只要看相关章节就行了,前者更系统一些(孙老师的课讲得很好),后者代码范例更多一些.
    lovepython
        14
    lovepython  
    OP
       2016-01-21 14:31:01 +08:00
    @hitmanx 感谢,那我去看相关书籍

    现代操作系统(原书第 3 版) [荷] Andrew S.Tanenbaum 著;陈向群,马洪兵 等 译 京东上看到这个
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3791 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 10:21 · PVG 18:21 · LAX 03:21 · JFK 06:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.