C 在尝试使用多对多实现时避免饥饿

C 在尝试使用多对多实现时避免饥饿,c,pthreads,semaphore,starvation,C,Pthreads,Semaphore,Starvation,我试图将对共享资源的访问权限授予两种类型的线程。当且仅当多个线程属于同一类型时,它可以被多个线程访问。让我们考虑黑人和白人。当资源被白人使用时,黑人不能使用,反之亦然 我尝试使用信号量来实现这一点。一旦一个黑人试图访问资源,它将增加黑人的数量,如果这个数字是1,它将阻止白人访问它 问题:当每种类型的线程超过1个时(在我的例子中,id为0的线程从未使用过它),就会出现明显的饥饿。我试图通过添加一个额外的信号量作为队列来解决这个问题 观察:这与读者-作者问题非常相似,只是有一个多对多的访问标准。(它

我试图将对共享资源的访问权限授予两种类型的线程。当且仅当多个线程属于同一类型时,它可以被多个线程访问。让我们考虑黑人和白人。当资源被白人使用时,黑人不能使用,反之亦然

我尝试使用信号量来实现这一点。一旦一个黑人试图访问资源,它将增加黑人的数量,如果这个数字是1,它将阻止白人访问它

问题:当每种类型的线程超过1个时(在我的例子中,id为0的线程从未使用过它),就会出现明显的饥饿。我试图通过添加一个额外的信号量作为队列来解决这个问题

观察:这与读者-作者问题非常相似,只是有一个多对多的访问标准。(它可以被同一类型的多个线程使用)最近我一直在为这个问题绞尽脑汁,我似乎不明白该如何处理这个问题

现在,对于一些代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <pthread.h>
#include <semaphore.h>

#define MAX_RAND 100
#define TRUE 1
#define FALSE 0

#define WHITES 3
#define BLACKS 2

#define MAX_WORLOAD 10

sem_t semaphore;
sem_t resource_semaphore;
sem_t service_queue;
volatile int resource = 0;
volatile int currentWhites = 0;
volatile int currentBlacks = 0;

typedef struct
{
    char *type;
    int *id;
} data;

void *white(void *args)
{
    data *thread_data = (data *)args;
    int id = *(thread_data->id);
    char *type = thread_data->type;

    for (int i = 0; i < MAX_WORLOAD; i++)
    {
        sem_wait(&service_queue);
        sem_wait(&semaphore);
        sem_post(&service_queue);

        currentWhites++;
        if (currentWhites == 1)
        {
            sem_wait(&resource_semaphore);
        }
        sem_post(&semaphore);

        sem_wait(&semaphore);

        currentBlacks--;
        resource = rand() % MAX_RAND;
        printf("Thread %d of type %s has updated resource to %d\n\n", id, type, resource);

        if (currentWhites == 0)
        {
            sem_post(&resource_semaphore);
        }

        sem_post(&semaphore);
    }
}

void *black(void *args)
{
    data *thread_data = (data *)args;
    int id = *(thread_data->id);
    char *type = thread_data->type;

    for (int i = 0; i < MAX_WORLOAD; i++)
    {
        sem_wait(&service_queue);
        sem_wait(&semaphore);
        sem_post(&service_queue);
        currentBlacks++;
        if (currentBlacks == 1)
        {
            sem_wait(&resource_semaphore);
        }
        sem_post(&semaphore);

        sem_wait(&semaphore);

        currentBlacks--;
        resource = rand() % MAX_RAND;
        printf("Thread %d of type %s has updated resource to %d\n\n", id, type, resource);

        if (currentBlacks == 0)
        {
            sem_post(&resource_semaphore);
        }

        sem_post(&semaphore);
    }
}

data *initialize(pthread_t threads[], int size, char *type)
{
    data *args = malloc(sizeof(data) * size);
    int *id = malloc(sizeof(int));
    void *function;

    if (type == "WHITE")
    {
        function = white;
    }
    else
    {
        function = black;
    }

    for (int i = 0; i < size; i++)
    {
        *id = i;
        args[i].type = type;
        args[i].id = id;
        printf("Initializing %d of type %s\n", *args[i].id, args[i].type);
        pthread_create(&threads[i], NULL, function, (void **)&args[i]);
    }

    return args;
}

void join(pthread_t threads[], int size)
{
    for (int i = 0; i < size; i++)
    {
        pthread_join(threads[i], NULL);
    }
}

void initialize_locks()
{
    sem_init(&semaphore, 0, 1);
    sem_init(&resource_semaphore, 0, 1);
    sem_init(&service_queue, 0, 1);
}

int main()
{
    initialize_locks();
    pthread_t whites[WHITES];
    pthread_t blacks[BLACKS];
    char *white = "white";
    char *black = "black";
    data *whites_arg = initialize(whites, WHITES, white);
    data *blacks_arg = initialize(blacks, BLACKS, black);

    join(whites, WHITES);
    join(blacks, BLACKS);

    free(whites_arg);
    free(blacks_arg);
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义最大值为100
#定义真1
#定义FALSE 0
#定义白色3
#定义黑色2
#定义最大工作负载10
信号量;
sem\u t资源\u信号量;
服务队列;
volatile int resource=0;
volatile int currentWhites=0;
易失性int=0;
类型定义结构
{
字符*类型;
int*id;
}数据;
无效*白色(无效*参数)
{
数据*线程\数据=(数据*)参数;
int id=*(线程数据->id);
字符*类型=线程\数据->类型;
对于(int i=0;iid);
字符*类型=线程\数据->类型;
对于(int i=0;i
如果要强制两种类型的线程交替访问一个对象,可以使用两个信号量。让黑人和白人各自拥有自己的信号量,一个信号量以0键开始,另一个信号量以10键左右开始,然后让白人释放一个黑色信号量的键,黑人释放一个白色信号量的键,如果你有10个白色线程,当其中一个解锁时,你将无法放入第10个白线程,但你将能够放入一个黑线程,这样当所有白线程释放其密钥时,你将没有白线程当前正在访问该对象


TL;DR:两个互相发送而不是自己发送的信号量将允许组之间的交替,但是独立于此操作,您还需要确保白人不会在黑人还在的时候离开。

谢谢您的宝贵提示!我还注意到有一个指针错误弄乱了我的线程id。我不应该在该结构中使用int*作为id。你的解决方案对我有效。