C 按多对多类型限制资源访问

C 按多对多类型限制资源访问,c,multithreading,thread-safety,posix,starvation,C,Multithreading,Thread Safety,Posix,Starvation,免责声明:此帖子包含对以下答案所做的编辑,所有学分归各自所有者所有。 我试图实现一个问题,即一个资源可能被两种类型的线程使用。每种类型可以有更多线程。(4条白色螺纹和6条黑色螺纹)。任何数量的黑人都可以同时使用该资源。白色的也一样。我还是不能把我的头缠在这上面 我尝试使用互斥锁来实现这一点。我还想考虑到这个实现可能存在的饥饿问题,因此我决定检查某一类型的服务线程的数量是否已经达到,从而允许另一类型的线程工作。我似乎无法实施最新的计划 我还想考虑到,当其他类型想要使用资源时,它必须等待轮到它,以及

免责声明:此帖子包含对以下答案所做的编辑,所有学分归各自所有者所有。

我试图实现一个问题,即一个资源可能被两种类型的线程使用。每种类型可以有更多线程。(4条白色螺纹和6条黑色螺纹)。任何数量的黑人都可以同时使用该资源。白色的也一样。我还是不能把我的头缠在这上面

我尝试使用互斥锁来实现这一点。我还想考虑到这个实现可能存在的饥饿问题,因此我决定检查某一类型的服务线程的数量是否已经达到,从而允许另一类型的线程工作。我似乎无法实施最新的计划

我还想考虑到,当其他类型想要使用资源时,它必须等待轮到它,以及其他类型完成使用资源

编辑:我试图使用@Nominal Animal的解决方案,但似乎有时也会出现僵局。此外,我还向结构添加了缺少的回合。现在,我有一些额外的问题:

  • 这似乎是对的,但不起作用,为什么
  • 为什么在
    bblock\u lock()
现在,对于一些代码:

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

#define WHITES 31
#define BLACKS 33
#define TYPES 2
#define W_ID 0
#define B_ID 1

struct bwlock
{
    pthread_mutex_t lock;    /* Protects the rest of the fields */
    pthread_cond_t wait[2];  /* To wait for their turn */
    volatile int waiting[2]; /* Number of threads waiting */
    volatile int running[2]; /* Number of threads running */
    volatile int started[2]; /* Number of threads started in this turn */
    const int limit[2];      /* Maximum number of starts per turn */
    volatile int black;      /* Black threads' turn */
    volatile int turn;       /*The turn */
};

#define BWLOCK_INIT(whites, blacks, turn)                         \
    {                                                             \
        PTHREAD_MUTEX_INITIALIZER,                                \
            {PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER}, \
            {0, 0}, {0, 0}, {0, 0}, {whites, blacks}, 0, turn     \
    }

struct bwlock resource = BWLOCK_INIT(4, 5, W_ID);

void bwlock_unlock(struct bwlock *bwl, const int isblack)
{
    const int black = !!isblack; /* 0 if white, 1 if black */

    pthread_mutex_lock(&(bwl->lock));

    /* This thread is no longer using the resource. */
    bwl->running[black]--;

    /* Was this the last of this color, with others waiting? */
    if (bwl->running[black] <= 0 && bwl->waiting[!black])
    {
        /* Yes. It's their turn. */
        if (bwl->turn == black)
        {
            bwl->turn = !black;
            /* Clear their started counter. */
            bwl->started[!black] = 0;
        }
        /* Wake them all up. */
        pthread_cond_broadcast(&(bwl->wait[!black]));
    }

    pthread_mutex_unlock(&(bwl->lock));
}

void bwlock_lock(struct bwlock *bwl, const int isblack)
{
    const int black = !!isblack; /* 0 if white, 1 if black */

    pthread_mutex_lock(&(bwl->lock));
    while (1)
    {

        /* No runners or waiters of the other color? */
        if (!(bwl->waiting[!black] < 1) && bwl->running[!black] < 1)
        {
            /* No; we can run. Does this change the turn? */
            if (bwl->turn != black)
            {
                bwl->turn = black;
                /* Clear started counter. */
                bwl->started[black] = 0;
            }
            break;
        }

        /* Still our turn, and not too many started threads? */
        if (bwl->turn == black && bwl->started[black] < bwl->limit[black])
            break;

        /* We must wait. */
        bwl->waiting[black]++;
        pthread_cond_wait(&(bwl->wait[black]), &(bwl->lock));
        bwl->waiting[black]--;
    }

    bwl->started[black]++;
    bwl->running[black]++;

    pthread_mutex_unlock(&(bwl->lock));
}

typedef struct
{
    int thread_id;
    char *type;
    int type_id;
} data;

void use_resource(int thread_id, char *type)
{
    printf("U: Thread %d of type %s is using the resource!\n", thread_id, type);
}

void take_resource(int thread_id, char *type, int type_id)
{
    printf("W:Thread %d of type %s is trying to get the resource!\n", thread_id, type);
    bwlock_lock(&resource, type_id);
    printf("W:Thread %d of type %sB got resource!\n", thread_id, type);
}

void release_resource(int thread_id, char *type, int type_id)
{
    bwlock_unlock(&resource, type_id);
    printf("R:Thread %d of type %s has released the resource!\n", thread_id, type);
}

void *doWork(void *arg)
{
    data thread_data = *((data *)arg);

    int thread_id = thread_data.thread_id;
    char *type = thread_data.type;
    int type_id = thread_data.type_id;
    take_resource(thread_id, type, type_id);
    use_resource(thread_id, type);
    release_resource(thread_id, type, type_id);

    return NULL;
}

data *initialize(pthread_t threads[], int size, char *type, int type_id)
{
    data *args = malloc(sizeof(data) * size);
    for (int i = 0; i < size; i++)
    {
        args[i].type = type;
        args[i].thread_id = i;
        args[i].type_id = type_id;
        pthread_create(&threads[i], NULL, doWork, (void **)&args[i]);
    }
    return args;
}

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

int main()
{
    pthread_t whites[WHITES];
    pthread_t blacks[BLACKS];
    char *white = "WHITE";
    char *black = "BLACK";
    data *w_args = initialize(whites, WHITES, white, W_ID);
    data *b_args = initialize(blacks, BLACKS, black, B_ID);

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

    free(w_args);
    free(b_args);

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#定义白色31
#定义黑人33
#定义类型2
#定义W_ID 0
#定义B_ID 1
结构bblock
{
pthread_mutex_t lock;/*保护其余字段*/
pthread_cond_t wait[2];/*等待轮到他们*/
volatile int waiting[2];/*等待的线程数*/
volatile int正在运行[2];/*正在运行的线程数*/
volatile int已启动[2];/*本次启动的线程数*/
const int limit[2];/*每圈启动的最大次数*/
volatile int black;/*黑色线程的回合*/
易失性整数回合;/*回合*/
};
#定义BWLOCK_INIT(白色、黑色、转弯)\
{                                                             \
PTHREAD_MUTEX_初始值设定项\
{PTHREAD_COND_初始值设定项,PTHREAD_COND_初始值设定项}\
{0,0},{0,0},{0,0},{白人,黑人},0,转身\
}
struct bwlock resource=bwlock_INIT(4,5,W_ID);
void bwlock_unlock(结构bwlock*bwl,常量int为黑色)
{
常量int black=!!isblack;/*0(如果为白色),1(如果为黑色)*/
pthread_mutex_lock(&(bwl->lock));
/*此线程不再使用该资源*/
bwl->正在运行[黑色]--;
/*这是最后一种颜色吗,其他人还在等着呢*/
如果(bwl->正在运行[黑色]等待[!黑色])
{
/*是的,轮到他们了*/
如果(bwl->转弯==黑色)
{
bwl->转弯=!黑色;
/*清除他们的计数器*/
bwl->已启动[!黑色]=0;
}
/*把他们都叫醒*/
pthread_cond_广播(&(bwl->wait[!black]);
}
pthread_mutex_unlock(&(bwl->lock));
}
void bwlock_lock(结构bwlock*bwl,常量int为黑色)
{
常量int black=!!isblack;/*0(如果为白色),1(如果为黑色)*/
pthread_mutex_lock(&(bwl->lock));
而(1)
{
/*没有其他颜色的跑步者或侍者*/
如果(!(bwl->waiting[!black]<1)和&bwl->running[!black]<1)
{
/*不,我们可以跑。这会改变转弯吗*/
如果(bwl->转弯!=黑色)
{
bwl->转弯=黑色;
/*清除启动计数器*/
bwl->已启动[黑色]=0;
}
打破
}
/*还是轮到我们了,没有太多开始的线程*/
如果(bwl->turn==black&&bwl->started[black]limit[black])
打破
/*我们必须等待*/
bwl->等待[黑色]+;
pthread_cond_wait(&(bwl->wait[black]),&(bwl->lock));
bwl->等待[黑色]--;
}
bwl->已启动[黑色]+;
bwl->运行[黑色]+;
pthread_mutex_unlock(&(bwl->lock));
}
类型定义结构
{
int-thread_-id;
字符*类型;
int-type_-id;
}数据;
无效使用资源(int-thread\u-id,char*类型)
{
printf(“U:Thread%d,类型%s,正在使用资源!\n”,Thread\U id,类型);
}
void take_资源(int thread_id,char*type,int type_id)
{
printf(“W:Thread%d,类型%s,正在尝试获取资源!\n”,Thread\u id,类型);
bblock_lock(资源和类型,id);
printf(“W:线程%d,类型%sB已获得资源!\n”,线程id,类型);
}
无效释放资源(int-thread\u-id、char*type、int-type\u-id)
{
bBlock_unlock(资源和类型,id);
printf(“R:Thread%d,类型%s,已释放资源!\n”,Thread\u id,类型);
}
void*doWork(void*arg)
{
数据线程_data=*((数据*)arg);
int thread\u id=thread\u data.thread\u id;
char*type=thread\u data.type;
int type_id=线程数据类型_id;
获取资源(线程id、类型、类型id);
使用资源(线程id、类型);
释放资源(线程id、类型、类型id);
返回NULL;
}
数据*初始化(pthread\u t threads[],int size,char*类型,int type\u id)
{
数据*args=malloc(sizeof(数据)*大小);
对于(int i=0;i
这有
struct bwlock {
    pthread_mutex_t    lock;        /* Protects the rest of the fields */
    pthread_cond_t     wait[2];     /* To wait for their turn */
    volatile int       waiting[2];  /* Number of threads waiting */
    volatile int       running[2];  /* Number of threads running */
    volatile int       started[2];  /* Number of threads started in this turn */
    const int          limit[2];    /* Maximum number of starts per turn */
    volatile int       black;       /* Black threads' turn */
};
#define BWLOCK_INIT(whites, blacks) \
    { PTHREAD_MUTEX_INITIALIZER, \
      { PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER }, \
      { 0, 0 }, { 0, 0 }, { 0, 0 }, { whites, blacks }, 0 \
    }
void bwlock_unlock(struct bwlock *bwl, const int isblack)
{
    const int black = !!isblack;  /* 0 if white, 1 if black */

    pthread_mutex_lock(&(bwl->lock));

    /* This thread is no longer using the resource. */
    bwl->running[black]--;

    /* Was this the last of this color, with others waiting? */
    if ((bwl->running[black] <= 0) && (bwl->waiting[!black] > 0)) {
        /* Yes. It's their turn. */
        if (bwl->black == black) {
            bwl->black = !black;
            /* Clear their started counter. */
            bwl->started[!black] = 0;
        }
        /* Wake them all up. */
        pthread_cond_broadcast(&(bwl->wait[!black]));
    }

    pthread_mutex_unlock(&(bwl->lock));
    return;
}
void bwlock_lock(struct bwlock *bwl, const int isblack)
{
    const int  black = !!isblack; /* 0 if white, 1 if black */

    pthread_mutex_lock(&(bwl->lock));
    while (1) {

        /* No runners or waiters of the other color? */
        if ((bwl->waiting[!black] < 1) && (bwl->running[!black] < 1)) {
            /* No; we can run. Does this change the turn? */
            if (bwl->black != black) {
                bwl->black = black;
                /* Clear started counter. */
                bwl->started[black] = 0;
            }
            break;
        }

        /* Still our turn, and not too many started threads? */
        if ((bwl->black == black) && (bwl->started[black] < bwl->limit[black]))
            break;

        /* We must wait. */
        bwl->waiting[black]++;
        pthread_cond_wait(&(bwl->wait[black]), &(bwl->lock));
        bwl->waiting[black]--;
    }

    bwl->started[black]++;
    bwl->running[black]++;

    pthread_mutex_unlock(&(bwl->lock));
}