ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

多线程同步的相关问题

2021-06-09 22:33:56  阅读:187  来源: 互联网

标签:同步 哲学家 int NULL include pthread 相关 sem 多线程


一、 生产者消费者问题
生产者消费者共享缓冲区,生产者向缓冲区中放数据,消费者从缓冲取中取数据,当缓冲区中被放满时,生产者进程就必须进入挂起状态,直到消费者从缓冲中取走数据时,生产者才能继续向缓冲区中存放数据,同样当缓冲取中没有数据时,消费者进程就必须进入挂起休眠状态,直到生产者向缓冲区中放入数据时,消费者才能被唤醒继续从缓冲区中取走数据。

在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这种生产消费能力不均衡的问题,所以便有了生产者和消费者模式。
————————————————
采用互斥锁实现,线程间同步

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#define bufsize 10 //设置缓存区大小
typedef struct node
{
    int val;
    struct node *next;
} node;
int count = 0;
node *head = NULL;
pthread_mutex_t point = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t full = PTHREAD_COND_INITIALIZER;   
pthread_cond_t empty = PTHREAD_COND_INITIALIZER;
void *producer()
{
    node *t;
    while (1)
    {
        pthread_mutex_lock(&point);
        while (count >= bufsize)
            pthread_cond_wait(&full, &point);
        t = (node *)malloc(sizeof(node));
        t->val = rand() % 100 + 1;
        count++;
        t->next = head;
        head = t;
        printf("--producer %d count %d \n", t->val, count);
        pthread_mutex_unlock(&point);
        pthread_cond_signal(&empty);
        sleep(rand() % 2);
    }
}
void *consumer()
{
    node *t;
    while (1)
    {
        pthread_mutex_lock(&point);
        while (count == 0)
            pthread_cond_wait(&empty, &point);
        t = head;
        head = head->next;
        printf("--consumer %d count %d\n", t->val, count);
        free(t);
        count--;
        pthread_mutex_unlock(&point);
        pthread_cond_signal(&full);
        sleep(rand() % 5);
    }
}
int main()
{
    pthread_t cid, pid;
    srand(time(NULL));
    if (pthread_create(&pid, NULL, producer, NULL) != 0)
    {
        perror("pthread_creat cid error:");
        exit(1);
    }
    if (pthread_create(&cid, NULL, consumer, NULL) != 0)
    {
        perror("pthread_creat pid error:");
        exit(1);
    }
    pthread_join(pid, NULL);
    pthread_join(cid, NULL);
    return 0;
}

二、 哲学家问题
有五个哲学家绕着圆桌坐,每个哲学家面前有一盘面,两人之间有一支筷子,这样每个哲学家左右各有一支筷子。哲学家有2个状态,思考或者拿起筷子吃饭。如果哲学家拿到一只筷子,不能吃饭,直到拿到2只才能吃饭,并且一次只能拿起身边的一支筷子。一旦拿起便不会放下筷子直到把饭吃完,此时才把这双筷子放回原处。如果,很不幸地,每个哲学家拿起他或她左边的筷子,那么就没有人可以吃到饭了。
思路:采用信号量保持线程同步/互斥,临界区访问问题以及避免死锁。

方法1:同时让4个哲学家进行竞争5个筷子,避免死锁

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <semaphore.h>
#define n 5 //五个哲学家
sem_t a[n]; //n个信号量代表筷子
sem_t t;
void *ptr1(void *arg) //方法1:同时让4个哲学家进行竞争5个筷子,避免死锁
{
    int i = (*(int *)arg);
    while (1)
    {
        printf("哲学家%d思考\n", i);
        sem_wait(&t);
        printf("哲学家%d饿了\n", i);
        sem_wait(&a[i]);
        printf("哲学家%d拿起了%d筷子,一根不能吃\n", i, i);
        sem_wait(&a[(i + 1) % n]);
        printf("哲学家%d拿起了%d %d筷子,开始吃饭\n", i, i, (i + 1) % n);
        sleep(3);
        sem_post(&a[i]);
        sem_post(&(a[(i + 1) % n]));
        sem_post(&t);
    }
}
int main()
{
    pthread_t b[5];
    sem_init(&t, 0, 4); //设置信号量为4,即同时只有4位发生竞争
    for (int i = 0; i < 5; i++)
    {
        sem_init(&a[i], 0, 1);
        pthread_create(&b[i], NULL, ptr1, &i);
    }
    for (int i = 0; i < n; i++)
    {
        pthread_join(b[i], NULL);
    }
    for (int i = 0; i < n; i++)
    {
        sem_destroy(&a[i]);
    }
    return 0;
}

方法2:同时让4个哲学家进行竞争5个筷子,避免死锁

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <semaphore.h>
#define n 5 //五个哲学家
sem_t a[n]; //n个信号量代表筷子
sem_t t;
void *ptr2(*arg) //方法2:对于一个哲学家要就餐,如果能同时拿到2根筷子就餐,
{                //如果不行,就释放所有筷子
    int i = (*(int *)arg);
    while (1)
    {
        if(sem_trywait(&a[i])==-1)
        continue;
        printf("哲学家%d拿起了%d筷子,一根不能吃\n", i, i);
        sleep(rand()%3);
        if (sem_trywait(&a[(i+1)%n])==-1)
        {
            sem_post(&a[i]);
            continue;
        }
        printf("哲学家%d拿起了%d %d筷子,开始吃饭\n", i, i, (i + 1) % n);
        sleep(rand()%3);
        sem_post(&a[i]);
        sem_post(&(a[(i + 1) % n]));
    }
}
int main()
{
    pthread_t b[5];
    srand(time(NULL));
    sem_init(&t, 0, 4); //设置信号量为4,即同时只有4位发生竞争
    for (int i = 0; i < 5; i++)
    {
        sem_init(&a[i], 0, 1);
        pthread_create(&b[i], NULL, ptr2, &i);
    }
    for (int i = 0; i < n; i++)
    {
        pthread_join(b[i], NULL);
    }
    for (int i = 0; i < n; i++)
    {
        sem_destroy(&a[i]);
    }
    return 0;
}

/

方法3:对于奇数先左后右,偶数相反

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <semaphore.h>
#define n 5 //五个哲学家
sem_t a[n]; //n个信号量代表筷子
sem_t t;
pthread_mutex_t ltck;
void *ptr2(*arg) //方法3:对于奇数先左后右,偶数相反
{   
    int i = (*(int *)arg);
    while (1)
    {
        printf("哲学家%d思考\n", i);
        printf("哲学家%d饿了\n", i);
        if (i % 2 == 0)
        {
            sem_wait(&a[i]);
            printf("哲学家%d拿起了%d筷子,一根不能吃\n", i, i);
            sem_wait(&a[(i + 1) % n]);
            printf("哲学家%d拿起了%d %d筷子,开始吃饭\n", i, i, (i + 1) % n);
        }
        else
        {
            sem_wait(&a[(i + 1) % n]);
            printf("哲学家%d拿起了%d筷子,一根不能吃\n", i, (i + 1) % n);
            sem_wait(&a[i]);
            printf("哲学家%d拿起了%d %d筷子,开始吃饭\n", i, (i + 1) % n, i);
        }
        sleep(rand()%3);
        sem_post(&a[i]);
        sem_post(&a[(i + 1) % n]);
    }
}
int main()
{
    pthread_t b[5];
    pthread_mutex_init(&ltck,NULL);
    srand(time(NULL));
    sem_init(&t, 0, 4); //设置信号量为4,即同时只有4位发生竞争
    for (int i = 0; i < 5; i++)
    {
        sem_init(&a[i], 0, 1); 
        pthread_create(&b[i], NULL, ptr2, &i);
    }
    for (int i = 0; i < n; i++)
    {
        pthread_join(b[i], NULL);
    }
    for (int i = 0; i < n; i++)
    {
        sem_destroy(&a[i]);
    }
    return 0;
}

标签:同步,哲学家,int,NULL,include,pthread,相关,sem,多线程
来源: https://blog.csdn.net/qq_52609580/article/details/117674848

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有