我正在尝试让我的程序执行此操作:
nrNodes
NrWorkers
当5个节点完成(sqrt值)时,它应该停止并进入 清理线程在链表中清除所有已完成的节点, 而且它将访问权限返回到有工作的其余线程
线程1: 获取semaphoreSlot(); 工作; 如果意外完成则发送信号; 直到列表解析;
线程2: 等待信号; 清洁; 返回对thread1的访问权限;
清洁后: 遇到的问题; 停止,没有退出;
代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <math.h>
#include <semaphore.h>
#define doneLimit 5
struct dataBlock{
struct node *root;
int listSize;
int forIndex;
};
struct node { // std linked list node
int value;
int worker;
struct node *next;
};
int done = 0;
sem_t sem;
pthread_mutex_t mutp; // mutex
pthread_cond_t condvar; //condvar
void *deleteDoneNodes(void *n){
pthread_cond_wait( &condvar, &mutp );
struct node *root = n;
struct node *it = root;
struct node *prev = NULL;
printf("Cleaning 1's \n");
do{
if(it->value == 1){
struct node *next = it->next;
if (prev != NULL) {
prev->next = next;
}
if (it == root) {
root = next;
}
free(it);
it = next;
}
else {
prev = it;
it = it->next;
}
}while(it != NULL);
done = 0;
pthread_exit(NULL);
}
void * worker( void *data ){
// get list
int wFlag;
struct dataBlock *inData = ( struct dataBlock * ) data;
struct node *root = inData->root;
int forIndex = inData->forIndex;
free(data);
// parse
while(1){
if( sem_wait( &sem ) != 0 ){
printf( " > waiting... \n" );
}
struct node *it = root;
printf(" Thread >>> %d --- %lu \n", forIndex, pthread_self() );
do{
wFlag = 0;
pthread_mutex_lock( &mutp );
if( forIndex == it->worker ){
if( it->value > 2 ){
while( it->value != 1 ){
it->value = sqrt(it->value);
}
printf("! node done\n");
pthread_mutex_unlock( &mutp );
wFlag += 1;
done += 1;
if( done == doneLimit ){ // limit 5
pthread_cond_signal( &condvar );
}
break;
}
}
else{
printf("...parsed done node. \n");
}
it = it->next;
pthread_mutex_unlock( &mutp );
}while(it != NULL);
sem_post(&sem);
sleep(1); // "create" concurrancy envi.
if ( wFlag == 0 ){
break;
}
}
pthread_exit(NULL);
}
int main( int argc, char *argv[] ){
if ( argc != 3 ){
printf( "Programm must be called with \n NR of elements and NR of workers! \n " );
exit( 1 );
}
int i;
struct node *root;
struct node *iterator;
//prepare list for task
int listSize = atoi(argv[1]);
int nrWorkers = atoi(argv[2]);
root = malloc(sizeof( struct node) );
root->value = rand() % 100;
root->worker = 0;
iterator = root;
for( i=1; i<listSize; i++ ){
iterator->next = malloc(sizeof(struct node));
iterator = iterator->next;
iterator->value = rand() % 100;
iterator->worker = i % nrWorkers;
printf("node #%d worker: %d value: %d\n", i, iterator->worker,iterator->value);
}
iterator->next = NULL;
printf("? List got populated\n");
// init semaphore > keeps max 3 threads working over the list
if( sem_init(&sem,0,3) < 0){
perror("semaphore initilization");
exit(0);
}
// Create all threads to parse the link list
int ret;
pthread_mutex_init( &mutp,NULL );
pthread_cond_init( &condvar, NULL );
pthread_t w_thread;
pthread_t* w_threads = malloc(nrWorkers * sizeof(w_thread));
for( i=0; i < nrWorkers; i++ ){
struct dataBlock *data = malloc(sizeof(struct dataBlock));
data->root = root;
data->listSize = listSize;
data->forIndex = i;
ret = pthread_create ( &w_threads[i], NULL, worker, (void *) data );
if( ret ) {
perror("Worker creation fail \n");
exit(2);
}
}
// Create Cleaning thread
pthread_t c_thread;
ret = pthread_create(&c_thread, NULL, deleteDoneNodes, (void *) root);
if ( ret ){
printf("Cleaner cration fail \n");
}
// Join threads
for ( i = 0; i < nrWorkers; i++ ){
pthread_join(w_threads[i],NULL);
}
iterator = root;
for ( i = 0; i < listSize; i++){
printf("val: %d worker: %d _ \n", iterator->value, iterator->worker);
iterator = iterator->next;
}
free( root );
pthread_mutex_destroy( &mutp );
pthread_cond_destroy( &condvar );
sem_destroy( &sem );
return 0;
}
PS : 有用 ./s 1 1 ./s 1 4 ./s 4 4 ./s 4 1
清洁工打电话后失败: 当x> = 5
时,它在./s x n处失败答案 0 :(得分:2)
至少你没有正确处理条件变量和互斥量的使用。
在调用后者之前,调用pthread_cond_wait()
的线程将锁定互斥锁。
从man pthread_cond_wait
逐字逐句
pthread_cond_wait 以原子方式解锁互斥锁(根据pthread_unlock_mutex)并等待条件变量cond为 信号。线程执行被暂停,不会消耗任何内容 CPU时间直到条件 变量发出信号。必须在进入pthread_cond_wait时由调用线程锁定互斥锁。在回到之前 调用线程,pthread_cond_wait重新获取互斥锁(按照 pthread_lock_mutex)。
此外,在从pthread_cond_wait()
调用返回后,互斥锁被锁定,并且必须在某个时间某个时候解锁。