01
迅雷面试题
编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。
分析
有三个线程,同一时刻只能有 1 个线程执行;
不合符执行条件的两个线程选择睡眠;
符合执行条件的线程执行打印操作,并且唤醒另外两个线程。
关键词
条件变量
互斥锁
线程同步
#include #include #include #include #include #define NUM 3int n = 0;//定义互斥锁并且初始化pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//定义条件变量并且初始化pthread_cond_t cond = PTHREAD_COND_INITIALIZER;void *thread_func(void *arg) { int param = (int)arg; char c = 'A' + param; int ret, i = 0; //每个线程循环 10 次打印编号 for (; i < 10; i++) { //执行循环体之前先加锁 pthread_mutex_lock(&mutex); //如果全局变量 n 和线程的编号(0 1 2)相等,则执行打印操作,否则停止运行 while (param != n) { ret = pthread_cond_wait(&cond, &mutex); if (ret != 0) { printf("thread %d wait failed:%s\n", param, strerror(ret)); } } printf("%c ", c); //全局变量 n 一直在 0 和 3 之间循环 n = (n + 1) % NUM; //释放互斥锁 pthread_mutex_unlock(&mutex); //唤醒等待的线程 pthread_cond_broadcast(&cond); } return (void *)0;}int main(int argc, char** argv){ int i = 0, err; pthread_t tid[NUM]; void *tret; for(; i < NUM; i++) { err = pthread_create(&tid[i], NULL, thread_func, (void *)i); if(err != 0) { printf("thread_create error:%s\n",strerror(err)); exit(-1); } } for (i = 0; i < NUM; i++) { err = pthread_join(tid[i], &tret); if (err != 0) { printf("can not join with thread %d:%s\n", i,strerror(err)); exit(-1); } } printf("\n"); return 0;}
运行结果
02
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....
请设计程序。
分析
操作第 1 个文件,保证线程 1 先运行;
操作第 2 个文件,保证线程 2 先运行;
以此类推。
关键词
条件变量
互斥锁
线程同步
#include #include #include #include #include #define NUM 4int n = 0;//定义互斥锁并且初始化pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //定义条件变量并且初始化pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//定义 4 个文件的文件描述符FILE *fp[NUM] = {0};void *thread_func(void *arg) { int param = (int)arg; int ret, i = 0, j = 0; int val = param + 1; //4 个文件,循环 4 次 for (j = 0; j < 4; j++) { //每个线程循环 2 次向文件输出 for (i = 0; i < 2; i++) { //执行循环体之前先加锁 pthread_mutex_lock(&mutex); //如果全局变量 n 和线程的编号(0 1 2 3)相等,则执行写文件操作,否则停止运行 while ((n + j) % NUM != param) { ret = pthread_cond_wait(&cond, &mutex); if (ret != 0) { printf("thread %d wait failed:%s\n", param, strerror(ret)); } } fprintf(fp[j], "%d ", val); //全局变量 n 一直在 0 和 3 之间循环 n = (n + 1) % NUM; //释放互斥锁 pthread_mutex_unlock(&mutex); //唤醒等待的线程 pthread_cond_broadcast(&cond); } //文件写完,睡眠 0.5S,保证 4 个线程都完成,再操作下一个文件 usleep(5000); } return (void *)0;}int main(int argc, char** argv){ int i = 0, err; pthread_t tid[NUM]; void *tret; char *name[NUM] = {"A", "B", "C", "D"}; for (i = 0; i < NUM; i++) { fp[i] = fopen(name[i], "w"); if (NULL == fp[i]) { printf("open file error:%s\n", strerror(err)); exit(-1); } } for(i = 0; i < NUM; i++) { err = pthread_create(&tid[i], NULL, thread_func, (void *)i); if(err != 0) { printf("thread_create error:%s\n",strerror(err)); exit(-1); } } for (i = 0; i < NUM; i++) { err = pthread_join(tid[i], &tret); if (err != 0) { printf("can not join with thread %d:%s\n", i,strerror(err)); exit(-1); } } for (i = 0; i < NUM; i++) { fclose(fp[i]); } return 0;}
运行结果
03
生产者消费者问题
有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个有多个缓冲区的缓冲池,生产者将它生产的产品放入一个缓冲区中,消费者可以从缓冲区中取走产品进行消费,所有生产者和消费者都是异步方式运行的,但它们必须保持同步,即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个已经装满产品且尚未被取走的缓冲区中投放产品。
分析
对生产者加锁;
判断缓冲区是否已满;如果已满,跳到步骤 4;
放入产品;
解锁,进入下一个循环。
#include #include #include #include #define NUMS 10 //表示生产,消费的次数 #define CAPACITY 5 //定义缓冲区最大值int capacity = 0; //当前缓冲区的产品个数pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //互斥量 //生产者线程void *produce(void *args){ int i = 0; for (; i < NUMS; ) { pthread_mutex_lock(&mutex); //加锁 if (capacity >= CAPACITY) //当前产品个数大于等于缓冲区最大值,则不把产品放入缓冲区。 { printf("缓冲区已满,无法放入产品\n"); } else //将产品放入缓冲区 { ++capacity; printf("生产者存入一个产品, 缓冲区大小为:%d\n", capacity); i++; } pthread_mutex_unlock(&mutex); } return ((void *) 0);}//消费者线程void *consume(void *args){ int i = 0; for (; i < NUMS; ) { pthread_mutex_lock(&mutex); if (capacity > 0) { --capacity; printf("消费者消耗一个产品,缓冲区大小为:%d\n", capacity); i++; } else { printf("缓冲区已空,无法消耗产品\n"); } pthread_mutex_unlock(&mutex); } return ((void *) 0);}int main(int argc, char** argv){ int err; pthread_t produce_tid, consume_tid; void *ret; err = pthread_create(&produce_tid, NULL, produce, NULL);//创建线程 if (err != 0) { printf("线程创建失败:%s\n", strerror(err)); exit(-1); } err = pthread_create(&consume_tid, NULL, consume, NULL); if (err != 0) { printf("线程创建失败:%s\n", strerror(err)); exit(-1); } err = pthread_join(produce_tid, &ret);//主线程等到子线程退出 if (err != 0) { printf("生产着线程分解失败:%s\n", strerror(err)); exit(-1); } err = pthread_join(consume_tid, &ret); if (err != 0) { printf("消费者线程分解失败:%s\n", strerror(err)); exit(-1); } return 0;}
运行结果
PS.春招已经如此艰难,备战秋招,刻不容缓。智能硬件VIP培训班,3个月教学+1个月项目实战。有需要得同学扫码咨询!