gpt4 book ai didi

c - Pthreads:无法将打印语句放在互斥体之外并成功运行。有什么办法可以实现这个效果吗?

转载 作者:行者123 更新时间:2023-11-30 16:39:15 25 4
gpt4 key购买 nike

简而言之,这段代码有 4 个线程在洞穴中争夺珍珠。他们应该从洞穴中取出珍珠,一次只能取出一颗,并在洞穴耗尽时停止。

当我将 printf() 放在互斥体中时,我的代码运行得很好,但是当我将其取出时,我得到错误的打印输出数据(尽管代码完成后最终值是正确的)。

我创建了一个特定于每个线程 ID 的结构(因此那里不会出现竞争条件),这样我就可以在每个线程执行后进行更新并以这种方式访问​​ printf() 中的数据。此结构中的数据是正确的,但导致问题的是在 printf 语句中访问它的方式。 printf() 语句使用 my_rank 打印正确的数据。当我将这个 printf() 移出锁时,运行时信息是错误的,因为(不知何故)线程 B 进入两次并打印相同的数据两次。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <math.h>

#define NUM_PIRATE_THREADS 4 /* number of pirate threads to run */
#define OPEN_SESAME 0 /* single bit value representation of password */
#define OPEN_WATERMELON 1 /* single bit value representation of password */
#define SLEEP_TIME 2 /* time for thread to sleep after execution */

/* percent value for "open, sesame" */
const double OPEN_SESAME_PERCENTAGE = 0.10;

/* percent value for "open, watermelon" */
const double OPEN_WATERMELON_PERCENTAGE = 0.15;

struct PirateBag {
char alphaForPirate;
double caveTotal;
double currentPearlsToTake;
double takePercentage;
};

/* pirate thread function */
void *pirate(void* rank);

/* pirate thread pearl removal and update function */
double executeRemoval(int *piratesBooty, struct PirateBag *piratesBag,
const long pirate_rank, const double cavePearls);

/* total number of items in resource (pearls in the cave) */
static double cavePearls = 1000.00;

/* mutual exlusion lock; mutual exclusion considered in this version */
pthread_mutex_t mutex;

/* array of pirate threads */
static pthread_t *thread_handles;

/* array to store the number of pearls garnered by each pirate */
int piratesBooty[NUM_PIRATE_THREADS];

/* array to store current pearls being retrieved from cave by pirate thread */
struct PirateBag piratesBag[NUM_PIRATE_THREADS];

/* main function */
int main() {

/* alert user pirate threads are about to begin consuming pearls */
printf("\nAvast matey, we are a'comin' fer yee pearls!!\n\n");

/* index variable for pirate threads */
long threadIndex;

/* char variable for pirate thread labeling (i.e. 1, 2, 3, ...) */
char alphaForPirate = 'A';

/* create and allocate memory for thread_handles array */
thread_handles = (pthread_t*)malloc(NUM_PIRATE_THREADS*sizeof(pthread_t));

/* create and run pirate threads...YAR!*/
for (threadIndex = 0; threadIndex < NUM_PIRATE_THREADS; ++threadIndex) {
pthread_create(&thread_handles[threadIndex], NULL,
pirate, (void*)threadIndex);
}

/* join pirate threads...AVAST MATEY!*/
for (threadIndex = 0; threadIndex < NUM_PIRATE_THREADS; ++threadIndex) {
pthread_join(thread_handles[threadIndex], NULL);
}

/* update your final cave pearl number to a whole integer value */
cavePearls = ceil(cavePearls);

/* display pearl data after pirate thread execution */
printf("\nYar!! The cave be empty!!\n\n");
for (threadIndex = 0; threadIndex < NUM_PIRATE_THREADS; ++threadIndex){
printf("Pirate %c got %d pearls\n",
alphaForPirate, piratesBooty[threadIndex]);
alphaForPirate++;
}
printf("\n");

/* free memory */
free(thread_handles);

return 0;
} /* end of main() */

/* pirate thread function */
void *pirate(void* rank) {

/* amount of pearls pirate thread may take during current entry to cave */
double pearlsToGrab = 0;

while(1) { /* continue execution while pearls remain in cave */

/* identify which pirate thread you are currently executing */
long my_rank = (long)rank;

/* make pirate thread sleep for SLEEP_TIME seconds */
sleep(SLEEP_TIME);

/* cave has been emptied, pirate thread should stop */
if (cavePearls < 1)
return 0;

/*****************************/
/* CRITICAL SECTION LOCKED */
pthread_mutex_lock(&mutex);

/* remove the correct number of pearls from the cave */
cavePearls -= executeRemoval(piratesBooty, piratesBag, my_rank, cavePearls);

/* print pirate thread data for current entry into the cave */
printf("Pirate %c gets %d of the pearls, %.f%% of %.0f pearls available in cave\n",
piratesBag[my_rank].alphaForPirate, (int)piratesBag[my_rank].currentPearlsToTake,
piratesBag[my_rank].takePercentage, piratesBag[my_rank].caveTotal);

/* CRITICAL SECTION UNLOCKED */
pthread_mutex_unlock(&mutex);
/*****************************/

} /* end of while-loop */

/* have pirate thread(s) terminate */
pthread_exit((void*)0);
}

/* pirate thread pearl removal and collection update function */
double executeRemoval(int *piratesBooty, struct PirateBag *piratesBag, const long pirate_rank,
const double cavePearls) {

/* cave has been emptied, pirate thread should stop */
if (cavePearls < 1)
return 0;

/* variable to capture correct pirate thread percentage of pearls to take */
double takePercentVal;

/* identify correct pirate thread percentage */
if (pirate_rank % 2 == OPEN_SESAME)
takePercentVal = OPEN_SESAME_PERCENTAGE;
else takePercentVal = OPEN_WATERMELON_PERCENTAGE;

/* update data for pirate thread */
piratesBooty[pirate_rank] += ceil(cavePearls * takePercentVal);
piratesBag[pirate_rank].alphaForPirate = (pirate_rank + 'A');
piratesBag[pirate_rank].caveTotal = cavePearls;
piratesBag[pirate_rank].currentPearlsToTake = ceil(cavePearls * takePercentVal);
piratesBag[pirate_rank].takePercentage = (takePercentVal * 100);

/* return number of pearls pirate thread should take */
return ceil(cavePearls * takePercentVal);
}

这是当我将 printf() 移出锁时出现的运行时错误:

海盗 A 获得 100 颗珍珠,洞穴中有 1000 颗珍珠的 10%

海盗 B 获得了 135 颗珍珠,洞穴中有 900 颗珍珠的 15%

海盗 B 获得了 135 颗珍珠,洞穴中有 900 颗珍珠的 15%

海盗 D 获得了 115 颗珍珠,洞穴中有 765 颗珍珠,其中 15%

最佳答案

是否将要打印的值复制到局部变量并打印副本?

如果您只是将调用移至 printf 函数,您还将对共享状态的读取移出临界区。

关于c - Pthreads:无法将打印语句放在互斥体之外并成功运行。有什么办法可以实现这个效果吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47117710/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com