子线程 printf_Linux多线程经典笔试题分享(附源码)

451b1f5cc8a6c3911caf344c19b0350b.png

01 

迅雷面试题

编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。

分析

  1. 有三个线程,同一时刻只能有 1 个线程执行;

  2. 不合符执行条件的两个线程选择睡眠;

  3. 符合执行条件的线程执行打印操作,并且唤醒另外两个线程。

关键词

  • 条件变量

  • 互斥锁

  • 线程同步

#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;}

运行结果

95bbbbaad966169be1f10713ac4a83e9.png

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 个文件,保证线程 1 先运行;

  2. 操作第 2 个文件,保证线程 2 先运行;

  3. 以此类推。

关键词

  • 条件变量

  • 互斥锁

  • 线程同步

#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;}

运行结果

3ddd5265c70503f5ba7c9803a5eb02b9.png

03

生产者消费者问题

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

分析

  1. 对生产者加锁;

  2. 判断缓冲区是否已满;如果已满,跳到步骤 4;

  3. 放入产品;

  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;}

运行结果

95c4bebc5adf9aad633e0b2aaa08c17d.png

abd902fbde35199f30d42c6319130be2.png

PS.春招已经如此艰难,备战秋招,刻不容缓。智能硬件VIP培训班,3个月教学+1个月项目实战。有需要得同学扫码咨询!

9a26c8d67149c19b2807aac2379fc0aa.png

c788d0ef57f65c323d572af14e0d1ed0.png

b6951b9b420ab3dc40a6c665ad6cb720.png

69a0d5b1deebee8ab1e9b92d693baaec.png

bbee7243651b301b2f78989b476e5473.png

bd8bec3ba766e94936a4cd26f0a55f92.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值