【发布时间】:2017-10-27 03:47:56
【问题描述】:
我有一个 C 程序,我必须编写它来创建 4 个线程。这 4 个“海盗”线程应该从“洞穴”(价值 1000 的双倍)中获取 1000 颗珍珠,从“洞穴”中取出 10% 或 15%。他们应该一次只去一个,当珍珠洞空了时,程序应该停止。该程序似乎运行正常,但在运行几次可执行文件后挂起。
为什么会这样?
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <math.h>
#define NUM_PIRATE_THREADS 4
#define OPEN_SESAME 0
#define OPEN_WATERMELON 1
/* array of threads */
static pthread_t *thread_handles;
/* mutual exlusion lock; mutual exclusion considered in this version */
pthread_mutex_t mutex;
/* pirate thread function */
void *pirate(void* rank);
/* total number of items in resource (pearls in the cave) */
static double cavePearls = 1000.00;
/* amount of pearls pirate thread may take */
static double pearlsToGrab;
/* array to store the number of pearls garnered by each pirate */
int piratesBooty[NUM_PIRATE_THREADS];
/* main function */
int main() {
/* variable to loop through threads and output pearl consumption */
long threadIndex;
/* thread variable */
long currentThread;
/* initialize thread_handles array */
thread_handles = (pthread_t*)malloc(NUM_PIRATE_THREADS*sizeof(pthread_t));
/* create pirate threads...ARGGG!*/
for (currentThread = 0; currentThread < NUM_PIRATE_THREADS; ++currentThread) {
pthread_create(&thread_handles[currentThread], NULL, (void *(*)(void *))pirate, (void*)currentThread);
}
/* join pirate threads...ARGGG!*/
for (currentThread = 0; currentThread < NUM_PIRATE_THREADS; ++currentThread) {
pthread_join(thread_handles[currentThread], NULL);
}
/* update your final cave pearl number to a whole integer value */
cavePearls = ceil(cavePearls);
/* display pearl data after thread(s) execution */
printf("\nPearls left in cave: %d\n", (int)cavePearls);
for (threadIndex = 0; threadIndex < NUM_PIRATE_THREADS; ++threadIndex){
printf("Pirate %ld: %d pearls\n", threadIndex, piratesBooty[threadIndex]);
}
/* free memory */
free(thread_handles);
return 0;
}
void *pirate(void* rank) {
while(1) { /* continue execution as long as there are still pearls in the cave */
if (cavePearls == 0) /* cave has been emptied, pirates should stop */
return 0;
/* identify which pirate thread you are executing */
long my_rank = (long)rank;
/* CRITICAL SECTION LOCKED */
pthread_mutex_lock(&mutex);
if (cavePearls) {
if (my_rank % 2 == OPEN_SESAME) { /* if thread is 0 or 2: "Open, sesame" pirate */
pearlsToGrab = cavePearls * 0.10; /* "open sesame" = 10% of pearls removed */
pearlsToGrab = ceil(pearlsToGrab); /* get the ceiling if not an integer value */
cavePearls = cavePearls - pearlsToGrab; /* update the number of pearls in cave */
piratesBooty[my_rank] += pearlsToGrab; /* update pirate thread total pearls taken */
}
else if (my_rank % 2 == OPEN_WATERMELON){ /* if thread is 1 or 3: "Open, watermelon" pirate */
pearlsToGrab = cavePearls * 0.15; /* "open watermelon" = 15% of pearls removed */
pearlsToGrab = ceil(pearlsToGrab); /* get the ceiling if not an integer value */
cavePearls = cavePearls - pearlsToGrab; /* update the number of pearls in cave */
piratesBooty[my_rank] += pearlsToGrab; /* update pirate thread total pearls taken */
}
} /* end of while-loop */
/* CRITICAL SECTION UNLOCKED */
pthread_mutex_unlock(&mutex);
/* DEBUG SCRIPT
printf("I am thread %ld, I have %d pearls, I'm taking %d pearls, and \nthere are %d pearls left"
"in the cave.\n\n", my_rank, piratesBooty[my_rank], (int)pearlsToGrab, (int)cavePearls);
*/
}
/* have thread(s) terminate */
pthread_exit((void*)0);
}
一切看起来都很好!进行了更改,事情看起来不错。如果您发现任何错误,请随时告诉我!
代码:
/*******************************************************************************
*******************************************************************************
Course: Operating Systems
Student: Douglas Adolph
Project: 3, Part 2
-------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
IMPORTANT NOTE:
///////////////////////////////////////////////////////////////////////////////
Some of this code borrows directly from material provided by Dr. Burtscher
in Texas State University's Parallel Programming course, as well as material
written by the author (Douglas Adolph) for said parallel programming course.
///////////////////////////////////////////////////////////////////////////////
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
SUMMARY:
///////////////////////////////////////////////////////////////////////////////
Program illustrates use of threads and mutual exclusion. N "pirates" (threads)
complete for 1000 pearls in a cave. Passwords are used to be granted a certain
percentage of the remaining pearls in the cave. Program should terminate when
all the pearls have been taken.
///////////////////////////////////////////////////////////////////////////////
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
PART 1 AND 2 SPECIFICS:
///////////////////////////////////////////////////////////////////////////////
Part 1: implementation with mutual exclusion NOT considered*
Part 2: implementation with mutual exclusion considered
*designed to fail during repeated runtime tests: demonstrate need for exclusion
*sleep() not used
///////////////////////////////////////////////////////////////////////////////
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
THREAD ID, THREAD PASSWORD, AND RESOURCE (PEARLS) RETRIEVAL INFORMATION:
///////////////////////////////////////////////////////////////////////////////
Pirate threads ID'd by rank (i.e. 0, 1, 2, ...), and this rank is used to ID
which password pirate thread will use. However, in the program output, pirate
threads are labeled alphanumerically (i.e. A, B, C, ...). However, although
pirate threads in output are labeled alphanumerically to match professor's
example, some liberty was taken in the final design of the output.
Note: if there are more than 26 pirate threads, the implementation of the output
of total pearls gathered by all pirate threads will need to be changed, or
labels for all pirate threads after Z will not have reasonable labels
"Open, sesame:" N/2 pirate processes use this password and
receive 10% of the remaining pearls
"Open, watermelon:" N/2 pirate processes use this password and
receive 15% of the remaining pearls
Even-numbered pirate threads will be assigned password "Open, sesame," where
password string is represented by 1 (*)
Odd-numbered pirate threads will be assigned password "Open, watermelon," where
password string is represented by 0 (*)
(*) via a modulus operation (thread % 2); string PWs/buffers avoided
///////////////////////////////////////////////////////////////////////////////
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
NOTES REGARDING TRANSFER AND EXECUTION OF FILE ON TEXAS STATE SERVERS:
///////////////////////////////////////////////////////////////////////////////
(1) transfer to Zeus for testing effected via:
scp /Users/douglasadolph/Desktop/School/CourseFolders/OperatingSystems/Projects
/YourProjects/project3_DouglasAdolph/FILE_NAME da1140@zeus.cs.txstate.edu:
(2) program compiled via:
gcc p3_part1_DouglasAdolph.c -o p3p1 -lpthread -lm
gcc p3_part2_DouglasAdolph.c -o p3p2 -lpthread -lm
///////////////////////////////////////////////////////////////////////////////
-------------------------------------------------------------------------------
*******************************************************************************
******************************************************************************/
#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 */
/* percent value for "open, sesame" */
const double OPEN_SESAME_PERCENTAGE = 0.10;
/* percent value for "open, watermelon" */
const double OPEN_WATERMELON_PERCENTAGE = 0.15;
/* array of pirate threads */
static pthread_t *thread_handles;
/* mutual exlusion lock; mutual exclusion considered in this version */
pthread_mutex_t mutex;
/* pirate thread function */
void *pirate(void* rank);
/* total number of items in resource (pearls in the cave) */
static double cavePearls = 1000.00;
/* array to store the number of pearls garnered by each pirate */
int piratesBooty[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(s) 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() */
void *pirate(void* rank) {
/* amount of pearls pirate thread(s) may take during current entry to cave */
static double pearlsToGrab = 0;
/* variables to output pirate thread(s) pearl consumption */
char alphaForPirate = 'A';
int piratePercentage;
/* label pirate thread(s) alphanumerically */
alphaForPirate += (long)rank;
while(1) { /* continue execution while pearls remain in cave */
if (cavePearls < 1) /* cave has been emptied, pirate thread(s) should stop */
return 0;
/* identify which pirate thread you are currently executing */
long my_rank = (long)rank;
/* if pirate thread is even: "Open, sesame" pirate */
if (my_rank % 2 == OPEN_SESAME) {
/* CRITICAL SECTION LOCKED */
pthread_mutex_lock(&mutex);
piratePercentage = (OPEN_SESAME_PERCENTAGE * 100);
pearlsToGrab = cavePearls * OPEN_SESAME_PERCENTAGE;
pearlsToGrab = ceil(pearlsToGrab);
cavePearls = cavePearls - pearlsToGrab;
piratesBooty[my_rank] += pearlsToGrab;
printf("Pirate %c gets %.0f of the pearls, %d percent of %.0f pearls available in cave\n",
alphaForPirate, pearlsToGrab, piratePercentage, (cavePearls + pearlsToGrab));
/* CRITICAL SECTION UNLOCKED */
pthread_mutex_unlock(&mutex);
}
/* if pirate thread is odd: "Open, watermelon" pirate */
else if (my_rank % 2 == OPEN_WATERMELON){
/* CRITICAL SECTION LOCKED */
pthread_mutex_lock(&mutex);
piratePercentage = (OPEN_WATERMELON_PERCENTAGE * 100);
pearlsToGrab = cavePearls * OPEN_WATERMELON_PERCENTAGE;
pearlsToGrab = ceil(pearlsToGrab);
cavePearls = cavePearls - pearlsToGrab;
piratesBooty[my_rank] += pearlsToGrab;
printf("Pirate %c gets %.0f of the pearls, %d percent of %.0f pearls available in cave\n",
alphaForPirate, pearlsToGrab, piratePercentage, (cavePearls + pearlsToGrab));
/* CRITICAL SECTION UNLOCKED */
pthread_mutex_unlock(&mutex);
}
/* make pirate thread(s) sleep for 2 seconds */
sleep(2);
} /* end of while-loop */
/* have pirate thread(s) terminate */
pthread_exit((void*)0);
}
【问题讨论】:
-
(void *(*)(void *))piratepirate 前面是什么乱七八糟的东西?据我所知pirate与pthread_create期望的函数签名相匹配.. 只需执行pthread_create(&thread_handles[currentThread], NULL, pirate, (void*)currentThread); -
还推荐
return 0;-->break;并将pearlsToGrab的声明移动到pirate函数中。 -
想想如果
pearlsToGrab接近但不完全为零会发生什么...... -
@AndrewHenle:没什么特别的。除了在应用
ceil之前的临时步骤(并且互斥锁被保存在那里,所以没有其他东西可以看到它),它是一个整数。
标签: c multithreading pthreads posix