注:数字代表行号
然后本人非计算机出身,如果问题太水,还请各位见谅
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 时,并不影响他的值。
1
xiaoshenke 2016-01-18 14:14:38 +08:00 via Android
你可以把主线程想象成你老师 你老师要干活的时候把活分给了你们班班委 班委之间是独立的
|
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 以上... |
3
lovepython OP @bluefalconjun 我的是 python 语言
|
4
lovepython OP @xiaoshenke 能针对我的三个疑问回答吗
|
5
bluefalconjun 2016-01-18 14:37:22 +08:00
@lovepython 发现了 ... 看来还是反应迟钝...
|
6
lovepython OP @bluefalconjun 你的 c 那个代码 kIcount 是全局的,两个线程操作,最后值能正确吗?函数里 int i,是不是每个线程都有一个这个 i,虽然代码是一份?即使中间执行到某个地方中断了,下次这个线程也会知道 i 的具体指。
|
7
bluefalconjun 2016-01-18 15:02:56 +08:00
|
8
xiaoshenke 2016-01-18 16:21:15 +08:00 via Android
每种系统里的线程语义是不一样的 你心中只要有一个大概运行的模型 就能很容易理解了 如果连线程到底是什么都不懂 就会越来越晕 多跑几个例子就懂了 别老看书
|
9
lovepython OP @xiaoshenke 什么叫大概模型啊,你说的举例我当然懂,问题得落实到代码上啊。
|
10
wizardforcel 2016-01-18 17:01:47 +08:00 via Android
线程的调度是由 os 控制的,你可以认为线程的执行顺序完全随机,会在每条原子指令执行后切换。保证原子性的办法就是加锁,或者使用原子操作库。对执行顺序不要做任何假设,保证顺序条件量的办法是条件量。
|
11
wizardforcel 2016-01-18 17:02:28 +08:00 via Android
@wizardforcel 保证执行顺序的办法就是使用条件量。
|
12
lovepython OP @wizardforcel 如果不做限制,也是就是线程的执行顺序随机,一个线程都执行半天了,可能另一个还没启动。
那这样,就应该是,一个线程执行到 3 ,有可能另一个线程从 2 刚开始执行,也有可能从 4 执行(比刚才那个线程启动得早,正好到 4 ,切换了) 这么理解对吧? |
13
hitmanx 2016-01-21 13:25:32 +08:00
你这个问题并不是 python 的问题,而是关于操作系统基础课里的问题.比如线程共享哪些变量,线程自己拥有什么变量,什么是原子操作,什么是锁\信号量,它在操作系统里是怎么实现的,线程是怎么调度的,这些抓起一本操作系统的书,都会很详细地和你解释,估计也就几十页,100 页,系统地看一下也不费多少时间
书的话我推荐<现代操作系统>, 视频教程我推荐哈工大孙志岗老师的"操作系统"公开课和网易公开课中斯坦福的<编程范式>.都只要看相关章节就行了,前者更系统一些(孙老师的课讲得很好),后者代码范例更多一些. |
14
lovepython OP |