POSIX - семафори, мутекси, нишки C

Имам това домашно в училище - завърших го, изпратих го и получих 0% :] ... Така че бих искал да попитам дали идеята ми е правилна. Например, ако искам да напиша програма с нишки - трябва да извикам 50 пъти thrfunction и имам 5 налични нишки (и трябва да ги използвам всички колкото е възможно повече). Бихте ли ми казали, моля, ако правя нещо нередно - предполагам, че съм, защото printf казва, че използвам само една нишка? Не съм много сигурен за метода, по който бих направил това нещо.

Благодаря предварително Nikolas Jíša

Ето моят изходен код:

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

#define THREADS 5
#define CYCLES 50

sem_t sem1;
pthread_mutex_t m1, m2;
long int result = 0;
int thread_status[THREADS]; // status of threads, value -1 for working thread, other values for free threads

typedef struct Arg {
    long int number;
    int thread_ID; } ARG;

void * thrfunction ( void * arg ) {
    int number = (( ARG * ) arg)->number, thread_ID = (( ARG * ) arg)->thread_ID, i;
    thread_status[thread_ID] = -1;
    pthread_mutex_unlock ( & m1 );
    for ( i = 0; i < number; i ++ );
    pthread_mutex_lock ( & m2 );
    result = result + number;
    printf ( "Thread  %d  result = %ld\n", thread_ID, result );
    pthread_mutex_unlock ( & m2 );
    pthread_mutex_lock ( & m1 );
    thread_status[thread_ID] = thread_ID;
    sem_post ( & sem1 );
    pthread_mutex_unlock ( & m1 );
    return NULL; }

int main ( int argc, char * argv[] ) {
    pthread_t thr[THREADS];
    pthread_attr_t Attr; pthread_attr_init ( & Attr ); pthread_attr_setdetachstate ( & Attr, PTHREAD_CREATE_JOINABLE );
    pthread_mutex_init ( & m1, NULL ); pthread_mutex_init ( & m2, NULL );
    sem_init ( & sem1, 0, THREADS );

    int i, j;
    ARG * pom = ( ARG * ) malloc ( sizeof ( * pom ) );

    for ( i = 0; i < THREADS; i ++ )
        thread_status[i] = i;

    for ( i = 0; i < CYCLES; i ++ ) {
        pom->number = rand () % 100000 * 10000;
        sem_wait ( & sem1 );
        pthread_mutex_lock ( & m1 );
        for ( j = 0 ; j == -1; j ++ );
            pthread_create ( & thr[j], & Attr, thrfunction, ( void * ) pom ); }
    free ( pom );
    pthread_attr_destroy ( & Attr ); pthread_mutex_destroy ( & m1 ); pthread_mutex_destroy ( & m2 ); sem_destroy ( & sem1 );
    for ( i = 0; i < THREADS; i ++ )
        pthread_join ( thr[i], NULL );
    return 0;}

person Nikolas Jíša    schedule 25.03.2011    source източник
comment
убедени ли сте със следния код? за (j = 0; j == -1; j ++); pthread_create (& thr[j], & Attr, thrfunction, (void *) pom);   -  person Srikanth    schedule 26.03.2011
comment
Да, така мисля... но съм много нов в това POSIX програмиране...   -  person Nikolas Jíša    schedule 26.03.2011
comment
Добра точка Srikanth. Николас, колко пъти очакваш за ( j = 0 ; j == -1; j ++ ); да стартира и какво очаквате да направи? Ако това е синхронизираща верига, това е много лоша идея. На C компилатор е позволено да премахне изцяло този цикъл, ако реши.   -  person Zan Lynx    schedule 26.03.2011
comment
Или ако сте компилирали на 64-битова система, вашата програма може никога да не завърши.   -  person Zan Lynx    schedule 26.03.2011
comment
С изключение на това след (j = 0; j == -1; j ++); j ще бъде идентификаторът на първата свободна нишка   -  person Nikolas Jíša    schedule 26.03.2011
comment
о, сега забелязах какво ми казваш, предполагам, че бях прекалено уморен вчера :) ... трябва да го коригирам (j = 0; thread_status[j] == -1; j ++), така че ще го пробвам: ] Благодаря   -  person Nikolas Jíša    schedule 26.03.2011


Отговори (1)


Първият проблем, който виждам е, че използвате ключалки твърде често.

Нишковото програмиране е много по-малко ефективно от последователното програмиране, ако всичко, което вашата програма прави, е да приема брави. Бравите струват време за вземане и освобождаване. Това време се отнема от работата, която вашата програма трябва да върши.

Вторият проблем, който виждам, е, че вашият for цикъл в thrfunction не прави нищо. Брои i от 0 до число? Това ли е всичко, което прави?

Третият проблем, който виждам, е, че извиквате free(pom) и извиквате pthread_mutex_destroy след създаването на всички нишки. ЛОШО! Нишките все още го използват! Нямате гаранция, че нишките дори са започнали да се изпълняват в този момент. Вашата операционна система може да отнеме секунди или дори минути (ако е имала малко RAM и е сменяна на диск), за да започне да изпълнява всички тези нишки, които сте създали.

Нещо, което може да намерите за полезно да помислите за нишките, е да запишете всяка „критична секция“, частите между ключалките, върху карти или да използвате нещо подвижно, за да представите тези части. Направете колона от тези карти или фигури за всяка нишка. Тези части могат да се движат навсякъде нагоре или надолу във времевата линия, освен ако ключалки, съединения, семафори или нещо друго не го възпрепятстват. Ако искате да сте наистина технически, оптимизацията на компилатора и изпълнението извън реда на процесора може дори да пренареди реда на изпълнение на частите в рамките на ограничения.

Някаква програма (не вашата) може да изглежда по следния начин (и вижте как нишката се забавя до една скорост при заключването в стъпка 7):

                0 <- parent process spawns threads
                1 <- parent process calls join to wait for thread in first column.
 2   2   2   
 3       3   
 4   3   4   
 5       5   2 
 6       6   3
             4
             5
             6
 7   4   7   7   <-- step 7 waits for lock
     5   8
     6   9
     7  10
        11       <- step 11 releases lock
 8
 9
10
11
     8
     9
    10
    11
             8
             9
            10
            11
12  12  12  12
13  13  13  13
14  14  14  14 <- step 14 each thread returns.
                15 <- parent process wait on thread 1 succeeds.
                16 <- wait for thread 2
                17 <- wait for thread 3
                18 <- wait for thread 4
                19 <- parent now cleans up thread data, lock data.
                20 <- parent exits.
person Zan Lynx    schedule 25.03.2011