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

2016-01-18 12:58:48 +08:00
 lovepython

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

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 时,并不影响他的值。

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

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


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

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

现代操作系统(原书第 3 版) [荷] Andrew S.Tanenbaum 著;陈向群,马洪兵 等 译 京东上看到这个

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/251544

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX