【发布时间】:2021-04-03 23:52:00
【问题描述】:
简介
通过这个程序,我打算学习 C 代码中的
此程序模拟产品 Q 和 R 的生产线:
Q 需要 1A、1B、1C,R 需要 1A、1C。
produce_Q 和 producer_R 函数共享相同的资源
代码
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
sem_t sem_worker[2]; //Semaphores (workers)
//Current stock (initialized as MAX stock)
int stock_A = 5;
int stock_B = 3;
int stock_C = 5;
//Q production method needs 1A, 1B and 1C
void *produce_Q(void *worker)
{
int w = (int) worker; //Worker id
//Wait if ther are not enough tools
while (stock_A < 1 || stock_B < 1 || stock_C < 1) {
printf("Not enough resources for worker[%d] for Q\n", w);
sem_wait(&sem_worker[w]); //Worker set to wait
sleep(4); //StackOverflow question here
printf("Resuming worker's [%d] production for Q\n", w);
}
//If there are tool to produce then
printf("Worker[%d] takes resources from pool for Q\n", w);
stock_A--;
stock_B--;
stock_C--;
printf("Stock: A=%d, B=%d, C=%d left\n", stock_A, stock_B, stock_C);
//Random wait to simulate prod
sleep(rand() % 4);
printf("Worker[%d] made a Q product\n", w);
//"Return" resources to stockpile
stock_A++;
stock_B++;
stock_C++;
printf("Worker[%d] returns stock for P product\n", w);
printf("Stock: A=%d, B=%d, C=%d left\n", stock_A, stock_B, stock_C);
}
//R prouction method, needs 1A, 1C
void *produce_R(void *worker)
{
int w = (int) worker; //Worker id
//Wait if ther are not enough tools
while (stock_A < 1 || stock_C < 1) {
printf("Not enough resources for worker[%d] for R\n", w);
sem_wait(&sem_worker[w]); //Worker set to wait
sleep(4); //Subject to change for sure
printf("Resuming worker's [%d] production for R\n", w);
}
//If there are tool to produce then
printf("Worker[%d] takes resources from pool for R\n", w);
stock_A--;
stock_B--;
stock_C--;
printf("Stock: A=%d, B=%d, C=%d left\n", stock_A, stock_B, stock_C);
//Random wait to simulate prod
sleep(rand() % 4);
printf("Worker[%d] made a R product\n", w);
//"Return" resources to stockpile
stock_A++;
stock_B++;
stock_C++;
printf("Worker[%d] returns stock for R product\n", w);
printf("Stock: A=%d, B=%d, C=%d left\n", stock_A, stock_B, stock_C);
}
int main(void) {
int i;
pthread_t th[4]; //Number of threads to work with
printf("Setting sems...");
if (sem_init(&sem_worker[0], 0, 1) < 0) error();
if (sem_init(&sem_worker[1], 0, 1) < 0) error();
if (sem_init(&sem_worker[2], 0, 1) < 0) error();
if (sem_init(&sem_worker[3], 0, 1) < 0) error();
//Create threads
printf("Create threads...");
for (i = 0; i < 4; i++){
if (pthread_create(&th[i], NULL, produce_Q, (void*)i) < 0) error(); //4Q production
if (pthread_create(&th[i], NULL, produce_R, (void*)i) < 0) error(); //4R production
}
//Wait for thread death
printf("Waiting for death...");
for (i = 0; i < 4; i++){
if (pthread_join(th[i], NULL) < 0) error();
}
return 0;
}
问题
我没有得到预期的输出,即每个函数执行 4 次(4Q 和 4R),有时 A、B 或 C 资源将为 0,并且其中一个线程将等待资源可用性。
我在这里控制:
while (stock_A < 1 || stock_B < 1 || stock_C < 1) {
printf("Not enough resources for worker[%d] for Q\n", w);
sem_wait(&sem_worker[w]); //Worker set to wait
sleep(4); //StackOverflow question here
printf("Resuming worker's [%d] production for Q\n", w);
}
但这还不够……我将“sleep(4)”实现为“有效的补丁”,但这并不能解决我的主要问题:
“有些工人在等待资源,但随后不生产, 我在那个等待代码块中遗漏了什么吗?”
【问题讨论】:
-
sleep()是一个计时函数,不是同步函数。您可以合理地使用它来模拟您正在模拟的生产机器实际花费的时间,但它在同步它们的活动中没有适当的作用。 -
您将
sem_worker声明为一个包含两个元素的数组,然后继续使用它,就好像它有四个元素一样。未定义的行为结果。 -
从多个线程对对象进行非同步、非只读、非原子访问的未定义行为。
标签: c multithreading pthreads semaphore