2015-02-09 2 views
1

Я потратил немало часов, пытаясь понять это, и я полностью застрял. Предполагается, что программа запустит 6 потоков. Где некоторые потоки начинаются там, где другие заканчиваются. Прямо сейчас, я пытаюсь выполнить один поток (поток 0) для выполнения. Закрытие комментариев комментариев, где я добавил код и сделал свои ошибки. Моя главная борьба здесь связана с указателями. Может ли кто-нибудь дать мне какие-либо указания (ha..ha ..: c)?Многопоточная семафорная программа

#include <stdlib.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <pthread.h> 
#include <semaphore.h> 
#define SHARED 1 
sem_t sem[6];   

struct threadargs 
{ 
int id;  /* thread number */ 
int sec;  /* how many sec to sleep */ 
int signal[6]; /* which threads to signal when done */ 
};     

void *tfunc(void *arg) 
{ 
int i; 
struct threadargs *targs=arg; 
sem_wait(sem);        //WAIT FOR OWN SEMAPHORE 
printf("Thread %d is running\n", targs->id); 
sleep(targs->sec); 
printf("Thread %d is completed and may wake others..\n", targs->id); 
for(i=0; i<6; i++)       //ITERATE OVER signal_ARRAY & 
    {           //WAKE THREAD NUMBER i IF 
    if(targs->signal[i] == 1)     //signal[i] IS 1 
    pthread_cond_signal(&sem[i]); 
    } 
} 

int main(void) 
{ 
int i, j; 
struct threadargs *targs[6]; 
pthread_t tid[6]; 
for(i=0; i<6; i++) 
{ 
targs[i] = (struct threadargs*) malloc(sizeof(struct threadargs)); 
for(j=0; j<6; j++) 
    { targs[i]->signal[j]=0; } 
} 
targs[0]->id=1;   
targs[0]->sec=1;   
targs[0]->signal[1]=1;  
targs[0]->signal[4]=1; 
sem[0] = 0;         //INITIALIZE THREAD'S SEMAPHORE TO 0 or 1 
pthread_create(targs[0], NULL, tfunc, NULL) // START THREAD 

for(i=0; i<6; i++) 
pthread_join(tid[i], NULL); 
return 0; 
} 
+3

Попробуйте: 'pthread_create (& tid [0], NULL, tfunc, (void *) таргеты [0]);' вместо того, что у вас есть. Кроме того, используйте 'sem_init (& sem [0], 0, 0);' вместо 'sem [0] = 0;'. Кроме того, 'sem_wait (sem)' будет блокироваться навсегда, поскольку вы никогда не отправляете сообщения на любые семафоры. – JS1

+0

Как указано в JS1, в вашей концепции есть некоторые недостатки. Я рекомендую следующую книгу, чтобы прояснить ситуацию для вас http://www.linuxine.com/node/266773 (это бесплатно). – PEdroArthur

+0

@ JS1 спасибо! Я буду продолжать пытаться :-) – Thomas

ответ

1

Хорошо. Прежде всего, я рекомендую второй раз взглянуть на ваш стиль кодирования. Это, конечно, очень субъективно, и я не буду говорить, что ваш плохой, но мне потребовалось некоторое время, чтобы понять это (если вы действительно хотите знать, я рекомендую коддля кода C/C++).

Позволяет решить вашу проблему. Насколько я вижу, основная проблема заключается в том, что вы в основном сравниваете указатели на яблоки с указателями на бананы (другими словами, вы используете неправильный тип указателя в неправильном месте).

Чтобы убедиться в том, что вызовы функций и т.п. правильно, убедитесь, что для поиска документации по API для функций, которые являются новыми для вас (примеры: pthread_create, sem_init, sem_wait, sem_post, pthread_cond_signal).

Как вы можете видеть, pthread_cond_signal не принимает аргумент sem_t *, поэтому вы не можете передать его ему и ожидать, что он будет работать. Ниже вы найдете пример программы, показывающей, как семафоры используются.

Во-первых, создается новый поток, который мгновенно будет находиться в состоянии ожидания. Как только основной протектор закончил отсчет от 0 до 150, он отправит («разблокирует») семафор и разрешит второй поток завершить свое выполнение.

#include <stdlib.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <pthread.h> 
#include <semaphore.h> 

static sem_t sem_thread_one; 
static pthread_t thread_one_data; 

static int x; 

static void *tfunc(void *arg) 
{ 
    sem_wait(&sem_thread_one); 
    printf("Thread 1 is running. The value of x is %i\n", x); 
    return NULL; 
} 

int main(int argc, char **argv) 
{ 
    sem_init(&sem_thread_one, 0 /* don't share between processes */, 0); 

    if(pthread_create(&thread_one_data, NULL, &tfunc, NULL)) { 
     fprintf(stderr, "Could not create thread, exiting!\n"); 
     return -EXIT_FAILURE; 
    } 

    while(x < 150) { 
     x++; 
    } 

    sem_post(&sem_thread_one); 

    if(pthread_join(thread_one_data, NULL)) { 
     fprintf(stderr, "Could not join threads, exiting!\n"); 
     return -EXIT_FAILURE; 
    } 

    sem_destroy(&sem_thread_one); 
    printf("Program ran succesfully!\n"); 
    return -EXIT_SUCCESS; 
} 

Сохранить в файле sem.c и компилировать & ссылку с помощью:

gcc -Wall -Os -pthread -o sem_test sem.c 

Теперь второй пример, но теперь с помощью pthread_cond_t. Функциональность программы несколько схожа, она ждет, когда счетчик достигнет определенного числа.

#include <stdlib.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <pthread.h> 

static pthread_t thread_one_data, thread_two_data; 
static volatile int x, y, idx = 10; 
static int count = 1; 

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 
static pthread_cond_t condition = PTHREAD_COND_INITIALIZER; 

static void *cond_test_wait(void *arg) 
{ 
    pthread_mutex_lock(&mutex); 
    while(count < 10) { 
     printf("Waiting for `count < 10' to become true\n"); 
     pthread_cond_wait(&condition, &mutex); 
    } 
    pthread_mutex_unlock(&mutex); 

    printf("Test wait thread finished. Value of count: %i\n", count); 
    return NULL; 
} 

static void *cond_test_signal(void *arg) 
{ 
    while(count < 10) { 
     pthread_mutex_lock(&mutex); 
     pthread_cond_signal(&condition); 

     /* do more intelligent things here */ 
     count++; 
     pthread_mutex_unlock(&mutex); 
    } 

    printf("Test signal thread finished\n"); 
    return NULL; 
} 

int main(int argc, char **argv) 
{ 

    if(pthread_create(&thread_one_data, NULL, &cond_test_wait, NULL)) { 
     fprintf(stderr, "Could not create thread, exiting!\n"); 
     return -EXIT_FAILURE; 
    } 

    if(pthread_create(&thread_two_data, NULL, &cond_test_signal, NULL)) { 
     fprintf(stderr, "Could not create thread, exiting!\n"); 
     return -EXIT_FAILURE; 
    } 

    pthread_join(thread_one_data, NULL); 
    pthread_join(thread_two_data, NULL); 

    pthread_cond_destroy(&condition); 
    pthread_mutex_destroy(&mutex); 

    printf("Program ran succesfully!\n"); 
    return -EXIT_SUCCESS; 
} 

Сохранить в файле cond.c и компилировать & ссылку с помощью:

gcc -o cond -pthread -Os -Wall cond.c 

Обратите внимание, насколько аккуратным условие работы в этом примере. Вы можете использовать их, чтобы ждать, пока какое-либо выражение (= условие) не станет истинным. После того, как условие станет истинным, нормальное выполнение продолжит.

Если вам нужна дополнительная помощь, не стесняйтесь спрашивать в комментариях. Удачи, сочетая приведенные выше примеры, чтобы исправить вашу программу.

+0

Спасибо, это полезная программа для лучшего понимания этого. Большая часть кода уже была предоставлена, чтобы продолжить.Я выполнил задание после получения дополнительной помощи, хотя мое понимание предоставленной программы все еще не на 100%. – Thomas