尝试使用多对多实现时避免饥饿
Avoiding starvation when attempting to use a many-to-many implementation
我正在尝试向两种类型的线程授予对共享资源的访问权限。它可以被多个线程访问,当且仅当该线程属于同一类型时。让我们考虑黑人和白人。当资源被白人使用时,黑人就不能使用,反之亦然。
我试图使用信号量来实现它。一旦黑人试图访问该资源,它将增加黑人的数量,如果该数字为 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;
}
如果你想强制两种类型的线程交替访问一个事物,你可以使用两个信号量。做到这一点,黑人和白人都有自己的信号量,一个信号量以 0 键开始,另一个以 10 或其他方式开始,然后让白人释放一个键给黑色信号量,黑人释放一个键给白色信号量,这样如果你有 10 个白色线程,当其中一个解锁时,你将无法放入第 10 个白色线程,但你可以放入黑色线程,这样当所有白线程释放它们的密钥,您当前将没有白线程正在访问该事物。
TL;DR: 两个信号量 post 彼此而不是它们自己将允许组之间的交替,但是独立于此操作,您还需要确保白人不会走,而黑人仍然英寸
我正在尝试向两种类型的线程授予对共享资源的访问权限。它可以被多个线程访问,当且仅当该线程属于同一类型时。让我们考虑黑人和白人。当资源被白人使用时,黑人就不能使用,反之亦然。
我试图使用信号量来实现它。一旦黑人试图访问该资源,它将增加黑人的数量,如果该数字为 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;
}
如果你想强制两种类型的线程交替访问一个事物,你可以使用两个信号量。做到这一点,黑人和白人都有自己的信号量,一个信号量以 0 键开始,另一个以 10 或其他方式开始,然后让白人释放一个键给黑色信号量,黑人释放一个键给白色信号量,这样如果你有 10 个白色线程,当其中一个解锁时,你将无法放入第 10 个白色线程,但你可以放入黑色线程,这样当所有白线程释放它们的密钥,您当前将没有白线程正在访问该事物。
TL;DR: 两个信号量 post 彼此而不是它们自己将允许组之间的交替,但是独立于此操作,您还需要确保白人不会走,而黑人仍然英寸