c-Pthreads:无法将print语句放在互斥对象之外并成功运行.有什么办法做到这一点吗



简而言之,此代码有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!!nn");
/* 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!!nn");
for (threadIndex = 0; threadIndex < NUM_PIRATE_THREADS; ++threadIndex){
printf("Pirate %c got %d pearlsn",
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 caven",
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函数,您还可以将共享状态的读取移出关键部分。

相关内容

最新更新