经典的面试题:用 4 个线程疯狂的打印 abcd 持续 5 秒钟,但是要按照顺序打印,不能是乱序的。
来源:互联网 发布:js 字符串转义 编辑:程序博客网 时间:2024/05/29 16:30
1.经典的面试题:用 4 个线程疯狂的打印 abcd 持续 5 秒钟,但是要按照顺序打印,不能是乱序的。
#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <string.h>#define THRNUM 4 static pthread_mutex_t mut[THRNUM];static int next(int a){ if(a+1 == THRNUM) return 0; return a+1;}static void *thr_func(void *p){ int n = (int)p; int ch = n + 'a'; while(1) { pthread_mutex_lock(mut+n); write(1,&ch,1); pthread_mutex_unlock(mut+next(n)); } pthread_exit(NULL);}int main(){ int i,err; pthread_t tid[THRNUM]; for(i = 0 ; i < THRNUM ; i++) { pthread_mutex_init(mut+i,NULL); pthread_mutex_lock(mut+i); err = pthread_create(tid+i,NULL,thr_func,(void *)i); if(err) { fprintf(stderr,"pthread_create():%s\n",strerror(err)); exit(1); } } pthread_mutex_unlock(mut+0); alarm(5); for(i = 0 ; i < THRNUM ; i++) pthread_join(tid[i],NULL); exit(0);}
上面这段代码是通过多个互斥量实现了一个锁链的结构巧妙的实现了要求的效果。
首先定义 4 个互斥量,然后创建 4 个线程,每个互斥量对应一个线程,每个线程负责打印一个字母。4 个线程刚刚被创建好时,4 把锁都处于锁定状态,4 个线程全部都阻塞在临界区之外,等 4 个线程全部都创建好之后解锁其中一把锁。被解锁的线程首先将自己的互斥量上锁,然后打印字符再解锁下一个线程对应的互斥量,然后再次等待自己被解锁。如此往复,使 4 个线程有条不紊的循环执行 锁定自己 --- 打印字符 -- 解锁下一个线程 的步骤,这样打印到控制台上的 abcd 就是有序的了。
从上面的例子可以看出来:互斥量限制的是一段代码能否执行,而不是一个变量或一个资源。上面的代码虽然使用锁链巧妙的完成了任务,但是它的实现方式并不是最漂亮的,更好的办法是条件变量。
这道题真正的考点其实是使用互斥量 + 条件变量的方式来实现。
#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <string.h>#include <unistd.h>#define THRNUM 4 static pthread_mutex_t mut_num = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t cond_num = PTHREAD_COND_INITIALIZER;static int num = 0;static int next(int a){ if(a+1 == THRNUM) return 0; return a+1;}static void *thr_func(void *p){ int n = (int)p; int ch = n + 'a'; while(1) { // 先抢锁,能抢到锁就可以获得打印的机会 pthread_mutex_lock(&mut_num); while(num != n) { // 抢到锁但是发现不应该自己打印,那就释放锁再出让调度器,让别人尝试抢锁 pthread_cond_wait(&cond_num,&mut_num); } write(1,&ch,1); num = next(num); /* * 自己打印完了,通知别人你们抢锁吧 * 因为不知道下一个应该运行的线程是谁, * 所以采用惊群的方式把它们全都唤醒, * 让它们自己检查是不是该自己运行了。 */ pthread_cond_broadcast(&cond_num); pthread_mutex_unlock(&mut_num); } pthread_exit(NULL);}int main(){ int i,err; pthread_t tid[THRNUM]; for(i = 0 ; i < THRNUM ; i++) { // 直接启动 4 个线程,让它们自己判断自己是否应该运行,而不用提前锁住它们 err = pthread_create(tid+i,NULL,thr_func,(void *)i); if(err) { fprintf(stderr,"pthread_create():%s\n",strerror(err)); exit(1); } } alarm(5); for(i = 0 ; i < THRNUM ; i++) pthread_join(tid[i],NULL); exit(0);}
2.如果面试的时候问你:处理常规任务时,是采用多线程比较快还是采用多进程比较快?
如果只回答多线程比较快,那么你工资一定多不了。
应该回答常规情况下是多线程较快,因为多进程需要重新布置进程的执行空间,还需要进行数据拷贝以及部分配置,所以会比创建线程慢xx倍。
不要只回答一个大方向就完事了,而是要量化你的答案,这样才能体现出来你在平时学习工作中很注重这些细节问题。
3.一个进程最多能创建多少个线程
一个进程能够创建多少个线程呢?主要受两个因素影响,一个是 PID 耗尽,一个是在之前的 C 程序地址空间布局时的阴影区域被栈空间占满了 。
PID 看上去是进程 ID,内核的最小执行单元其实是线程,实际上是线程在消耗 PID。一个系统中的线程可以有很多,所以 PID 被耗尽也是有可能的。
使用 ulimit(1) 命令可以查看栈空间的大小,阴影区剩余空间的大小 / 栈空间的大小 == 就是能创建的线程数量。
可以自己写个程序测试一下一个进程最多能够创建多少个线程,然后使用 ulimit(1) 命令修改栈的大小再测试几次,看看能有什么发现。代码很简单。
- 经典的面试题:用 4 个线程疯狂的打印 abcd 持续 5 秒钟,但是要按照顺序打印,不能是乱序的。
- 多线程按顺序依次打印ABCD---java多线程的一道经典面试题
- 顺序打印ABC------java多线程的一道经典面试题
- 一个关于线程的经典面试题,要求用三个线程,按顺序打印1,2,3,4,5.... 71,72,73,74, 75. 线程1先打印1,2,3,4,5, * 然后是线程2打印6,7,8,9,10, 然后是
- 剑指offer面试题:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字
- 14. 微软面试题:输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印。
- 经典的一道JAVA面试题:A、B线程循环打印A、B
- 回旋矩阵 (就是转圈圈打印的,经典面试题)
- 多线程编程(二)——面试题,每个线程只打印一种字符,多个线程协同顺序打印n次字符串(求大神的其他实现方案)
- 启动三个线程A,B,C,打印10次 按照ABC的顺序输出
- 3个线程每个线程只能打印自己的名字,在屏幕上顺序打印 ABC,打印10次
- 输入一个矩阵,按照从外到里以顺时针的顺序依次打印每一个数字
- 输入一个矩阵,按照从外向里顺时针的顺序依次打印出每一个数字
- 一道Java线程面试题。3个线程顺序打印10次ABC.
- 输入abcd 打印所有字母的组合
- 线程同步面试题,3个线程打印一个1-100的数组,要求P1=1,P2=2,P3=3,P1=4的形式
- 按照顺时针的顺序从外向里打印整形数组
- 面试题12:输入数字n,按照顺序打印出从1最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数即999
- xcode APP 打包以及提交apple审核详细流程(新版本更新提交审核)
- usbredir-0.7内容详解(二)
- 26.Struts2文件下载并在下载文件之前进行权限检查
- 网站所有页面都在新窗口打开
- fpga闪烁的led灯
- 经典的面试题:用 4 个线程疯狂的打印 abcd 持续 5 秒钟,但是要按照顺序打印,不能是乱序的。
- 多条件查询
- OCdemo-07 CateGory 类目
- android asp.net HttpURLConnection通信 中文乱码
- 9.Subsets
- 《剑指Offer》面试题:不使用加减乘除做加法运算
- Android-Fragment
- android 文件上传到服务器
- 向量旋转算法