您的位置:首页 > 职场人生

多线程面试题

2016-06-13 20:42 375 查看
多线程在笔试面试中经常出现,下面列出一些公司的多线程笔试面试题。首先是一些概念性的问答题,这些是多线程的基础知识,经常出现在面试中的第一轮面试(我参加2011年腾讯研究院实习生招聘时就被问到了几个概念性题目)。然后是一些选择题,这些一般在笔试时出现,虽然不是太难,但如果在选择题上花费大多时间无疑会对后面的编程题造成影响,因此必须迅速的解决掉。最后是综合题即难一些的问答题或是编程题。这种题目当然是最难解决了,要么会引来面试官的追问,要么就很容易考虑不周全,因此解决这类题目时一定要考虑全面和细致。

下面就来看看这三类题目吧。

   一。概念性问答题

   第一题:线程的基本概念、线程的基本状态及状态之间的关系?

概念:线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。

    好处 :

(1)易于调度。

               (2)提高并发性。通过线程可方便有效地实现并发性。进程可创建多个线程来执行同一程序的不同部分。

               (3)开销少。创建线程比创建进程要快,所需开销很少。。

               (4)利于充分发挥多处理器的功能。通过创建多线程进程,每个线程在一个处理器上运行,从而实现应用程序的并发性,使每个处理器都得到充分运行。

状态:运行、阻塞、挂起阻塞、就绪、挂起就绪

    状态之间的转换:准备就绪的进程,被CPU调度执行,变成运行态;

                                 运行中的进程,进行I/O请求或者不能得到所请求的资源,变成阻塞态;

                                 运行中的进程,进程执行完毕(或时间片已到),变成就绪态;

                                 将阻塞态的进程挂起,变成挂起阻塞态,当导致进程阻塞的I/O操作在用户重启进程前完成(称之为唤醒),挂起阻塞态变成挂起就绪态,当用户在I/O操作结束之前重启进程,挂起阻塞态变成阻塞态;

                                 将就绪(或运行)中的进程挂起,变成挂起就绪态,当该进程恢复之后,挂起就绪态变成就绪态;                

    第二题:线程与进程的区别?

   这个题目问到的概率相当大,计算机专业考研中也常常考到。要想全部答出比较难。

进程和线程的关系:

    (1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。

    (2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。

    (3)处理机分给线程,即真正在处理机上运行的是线程。

    (4)线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。线程是指进程内的一个执行单元,也是进程内的可调度实体.

进程与线程的区别:

    (1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位

    (2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行

    (3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.

    (4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。

   第三题:多线程有几种实现方法,都是什么?

C++中多线程实现方法:

windows下通过api CreateThread,linux下则常用pthread库,这些都是最底层的实现,最新的C++11标准里增加了std::thread多线程库,使用第三方库的话就更多了,比如boost的thread等等,不推荐使用vc自家的_beginthread,尤其有跨平台需求的时候。

Java中实现多线程的方法:

 1. 继承 Thread 类
    2. 实现 Runnable 接口再 new Thread(YourRunnableOjbect) 推荐

   第四题:多线程同步和互斥有几种实现方法,都是什么?

   2011年迅雷校园招聘时的一面和二面都被问到这个题目,回答的好将会给面试成绩加不少分。

   线程间的同步方法大体可分为两类:用户模式和内核模式。顾名思义,内核模式就是指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,而用户模式就是不需要切换到内核态,只在用户态完成操作。
用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。内核模式下的方法有:事件,信号量,互斥量。

   第五题:多线程同步和互斥有何异同,在什么情况下分别使用他们?举例说明。

当有多个线程的时候,经常需要去同步这些线程以访问同一个数据或资源。例如,假设有一个程序,其中一个线程用于把文件读到内存,而另一个线程用于统计文件中的字符数。当然,在把整个文件调入内存之前,统计它的计数是没有意义的。但是,由于每个操作都有自己的线程,操作系统会把两个线程当作是互不相干的任务分别执行,这样就可能在没有把整个文件装入内存时统计字数。为解决此问题,你必须使两个线程同步工作。

      所谓同步,是指散步在不同进程之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。如果用对资源的访问来定义的话,同步是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。

        所谓互斥,是指散布在不同进程之间的若干程序片断,当某个进程运行其中一个程序片段时,其它进程就不能运行它们之中的任一程序片段,只能等到该进程运行完这个程序片段后才可以运行。如果用对资源的访问来定义的话,互斥某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

     第六题:进程间通信的方式?

    (1)管道(pipe)及有名管道(named pipe):管道可用于具有亲缘关系的父子进程间的通信,有名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。

    (2)信号(signal):信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一致的。

    (3)消息队列(message queue):消息队列是消息的链接表,它克服了上两种通信方式中信号量有限的缺点,具有写权限得进程可以按照一定得规则向消息队列中添加新信息;对消息队列有读权限得进程则可以从消息队列中读取信息。

    (4)共享内存(shared memory):可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据得更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。

    (5)信号量(semaphore):主要作为进程之间及同一种进程的不同线程之间得同步和互斥手段。

    (6)套接字(socket):这是一种更为一般得进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛。

二。选择题

   第一题(百度笔试题):

   以下多线程对int型变量x的操作,哪几个不需要进行同步:

    A.x=y;      B. x++;    C.++x;    D. x=1;

  答案参见:http://blog.csdn.net/jjj19891128/article/details/24392229

    第二题(阿里巴巴笔试题)

   多线程中栈与堆是公有的还是私有的

    A:栈公有, 堆私有

    B:栈公有,堆公有

    C:栈私有, 堆公有D:栈私有,堆私有

一般来说栈是私有的

堆是共有的

但是你可以为特定的线程创建私有的堆
堆和栈的区别如下:

堆很灵活,但是不安全。对于对象,我们要动态地创建、销毁,不能说后创建的对象没有销毁,先前创建的对象就不能销毁,那样的话我们的程序就寸步难行,所以Java中用堆来存储对象。而一旦堆中的对象被销毁,我们继续引用这个对象的话,就会出现著名的 NullPointerException,这就是堆的缺点——错误的引用逻辑只有在运行时才会被发现。

栈不灵活,但是很严格,是安全的,易于管理。因为只要上面的引用没有销毁,下面引用就一定还在,所以,在栈中,上面引用永远可以通过下面引用来查找对象,同时如果确认某一区间的内容会一起存在、一起销毁,也可以上下互相引用。在大部分程序中,都是先定义的变量、引用先进栈,后定义的后进栈,同时,区块内部的变量、引用在进入区块时压栈,区块结束时出栈,理解了这种机制,我们就可以很方便地理解各种编程语言的作用域的概念了,同时这也是栈的优点——错误的引用逻辑在编译时就可以被发现。

总之,就是变量和对象的引用存储在栈区中,而对象在存储在堆中


三。综合题

   第一题(台湾某杀毒软件公司面试题):

   在Windows编程中互斥量与临界区比较类似,请分析一下二者的主要区别。

        两者都可以用于同一进程中不同子线程对资源的互斥访问。

        互斥量是内核对象,因此还可以用于不同进程中子线程对资源的互斥访问。

        互斥量可以很好的解决由于线程意外终止资源无法释放的问题。

    第二题:

   一个全局变量tally,两个线程并发执行(代码段都是ThreadProc),问两个线程都结束后,tally取值范围。

    inttally = 0;//glable

    voidThreadProc()

    {

    for(int i = 1; i <= 50;i++)

    tally += 1;

    }

 答:[50,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…

   请设计程序。

   下面的第六题与第七题也是在考研中或是程序员和软件设计师认证考试中的热门试题。

   第六题

   生产者消费者问题

   这是一个非常经典的多线程题目,题目大意如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个有多个缓冲区的缓冲池,生产者将它生产的产品放入一个缓冲区中,消费者可以从缓冲区中取走产品进行消费,所有生产者和消费者都是异步方式运行的,但它们必须保持同步,即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个已经装满产品且尚未被取走的缓冲区中投放产品。

   第七题

   读者写者问题

   这也是一个非常经典的多线程题目,题目大意如下:有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者读时写者也不能写。

   多线程相关题目就列举到此,如果各位有多线程方面的笔试面试题,欢迎提供给我,我将及时补上。谢谢大家。

参考文章:http://blog.csdn.net/dazhong159/article/details/7948327
一个牛逼的链接:http://blog.csdn.net/morewindows/article/details/7392749
程序解答:http://blog.csdn.net/lanyan822/article/details/7587972
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ 多线程 面试题