二.选择题
第一题(百度笔试题):
以下多线程对int型变量x的操作,哪几个不需要进行同步:
A. x=y; B. x++; C. ++x; D. x=1;
答案:ABC
A:在X86上它包含两个操作:读取y至寄存器,再把该值写入x。读y的值这个操作本身是原子的,把值写入x也是原子的,但是两者合起来不是原子操作,因为它不是不可再分的操作,所以需要进行同步
B、C:x++和++x这样的操作在多线程环境下是需要同步的。因为X86会按三条指令的形式来处理这种语句:从内存中读x的值到寄存器中,对寄存器加1,再把新值写回x 所处的内存地址
D:x=1是原子操作,不可再分
因为x是int类型,32位CPU上int占32位,在X86上由硬件直接提供了原子性支持。实际上不管有多少个线程同时执行类似x=1这样的赋值语句,x的值最终还是被赋的值(而不会出现例如某个线程只更新了x的低16位然后被阻塞,另一个线程紧接着又更新了x的低24位然后又被阻塞,从而出现x的值被损坏了的情况)。
第二题(阿里巴巴笔试题)
多线程中栈与堆是公有的还是私有的
A:栈公有, 堆私有
B:栈公有,堆公有
C:栈私有, 堆公有
D:栈私有,堆私有
答案:C,每个线程都有自己的栈,多个线程共有堆
三.综合题
第一题(台湾某杀毒软件公司面试题):
在Windows编程中互斥量与临界区比较类似,请分析一下二者的主要区别。
第二题:
一个全局变量tally,两个线程并发执行(代码段都是ThreadProc),问两个线程都结束后,tally取值范围。
inttally = 0;//glable
voidThreadProc()
{
for(inti = 1; i <= 50; i++)
tally += 1;
}
tally += 1 分为三条指令:
(1)tally内存进入寄存器;(2)寄存器加1;(3)寄存器数据放回内存tally;
最坏的情况: 就是线程一读tally,线程二也读tally,线程一寄存器加一,线程二寄存器加一,线程一放回tally,线程二放回tally,这种情况虽然二个线程都对tally加1,但显然只加了一次。所以到最后只加50次。
最好的情况: 就是线程一的for结束,再到线程二的for,一共执行100次。
第三题(某培训机构的练习题):
子线程循环 10 次,接着主线程循环 100 次,接着又回到子线程循环 10 次,接着再回到主线程又循环 100 次,如此循环50次,试写出代码。
第四题(迅雷笔试题):
编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。
第五题(Google面试题)
有四个线程1、2、3、4。线程1的功能就是输出1,线程2的功能就是输出2,以此类推.........现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式:
A:1 2 3 4 1 2....
B:2 3 4 1 2 3....
C:3 4 1 2 3 4....
D:4 1 2 3 4 1....
请设计程序。
下面的第六题与第七题也是在考研中或是程序员和软件设计师认证考试中的热门试题。
第六题
生产者消费者问题
这是一个非常经典的多线程题目,题目大意如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个有多个缓冲区的缓冲池,生产者将它生产的产品放入一个缓冲区中,消费者可以从缓冲区中取走产品进行消费,所有生产者和消费者都是异步方式运行的,但它们必须保持同步,即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个已经装满产品且尚未被取走的缓冲区中投放产品。
第七题
读者写者问题
这也是一个非常经典的多线程题目,题目大意如下:有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者读时写者也不能写。