szálak - első join- ig

Fórumok

Hi!

Van egy egyszerű kódrészlet:


 pthread_t th1, th2, th3;
 pthread_create(&th1, NULL, fv1, NULL);
 pthread_create(&th2, NULL, fv2, NULL);
 pthread_create(&th3, NULL, fv3, NULL);
 
 pthread_join(th1, NULL);
 
 ...
 
 print("Done\n");

Az th1 gyorsan lefut, de ez most nem is lényeges. Arra lenne szükségem, hogy a Done felirat az után jelenjen meg, hogy vagy lefutott a th2, vagy lefutott a th3 szál. Tehát szálak lefutására lehet tenni valamilyen logikai műveletet? Ha igen, hogyan?

Esetleg workaroundnak jó lenne egy olyan megoldás, ami ...- nál akkor fut tovább, ha vagy lefutott th2, vagy eltelt x idő a szálak létrehozásától számítva, és ekkor th3- ra nincs is szükség.

Remélem van itt ilyenkor valami c fan, mert kezdek a fenti problémámtól kiakadni :- ).

K§zi.

Hozzászólások

A pthread_mutex-szel kezdodo fuggvenyeket nezd meg szerintem.
0-ra inicializalod a mutex-ed, ... helyen 1-el csokkented az erteket, mig t2 es t3 vegen is 1-el noveled..
konkret implementaciot (a pthread-es fuggvenyekkel) most nem latom at, ahhoz vegig kellene olvasni.. eddig meg csak sima mutex-et hasznaltam, precessek kozt.. de az neked felesleges (es ide nem is jo)..
a mutex ugy szokott mukodni, hogy inicializalhatod valamire, es modosithatod az erteket valamivel.. ha a modositas hatasara 0 ala menne az erteke, akkor blokkolodik, egeszen, amig valami meg nem noveli annyira, hogy ne menjen 0 ala a modositas hatasara..
pl: foznel krumplilevest, ehhez kell 1 zsak krumpli.. (azaz a krumpli mennyisegere -1 zsak modosito, es ha nincs krumpli, nem tudsz fozni)
most 0 zsaknyi van
elkuldesz vkit a piacra egy zsakert (+1), es egy masikat a teszkoba szinten 1 zsak krumpliert..
ezutan varsz rajuk, mert -1 modositod van..
amint bejon az elso zsak, mar a mutex erteke 1 lesz, igy a -1 belefer.. elkezdheted vegrehajtani..
ha bejon utana a masodik zsak is, majd jo lesz legkozelebbre.. (ezzel mar nem foglalkozunk)
(eredetileg eroforrasfoglalasra talaltak ki)
--------------------
int iPhone,iMac,iPod; // Apple using Hungarian notation :)

Úgy értelemzem, hogy a th2 és th3-nak nem kell már befejeződnie, mivel "Done" után vagyunk. (Ha mégis meg kellene várni, akkor arra ott a pthread_join().) Ezért egyszerűen meghívod a pthread_cancel()-t, és megnézed, mi az eredmény. Ha 0, akkor még futott a szál; ha ESRCH, akkor már befejeződött.


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

void* fv1(void* p) {
        printf("fv1: Starting\n");
        printf("fv1: Exiting\n");
        return NULL;
}

void* fv2(void* p) {
        printf("fv2: Starting\n");
        printf("fv2: Exiting\n");
        return NULL;
}

void* fv3(void* p) {
        printf("fv3: Starting\n");
        printf("fv3: Exiting\n");
        return NULL;
}

int main() {
        pthread_t th1, th2, th3;
        int ret;

        ret = pthread_create(&th1, NULL, fv1, NULL);
        if (ret != 0) {
                printf("Cannot start th1, giving up.\n");
                exit(1);
        }
        ret = pthread_create(&th2, NULL, fv2, NULL);
        if (ret != 0) {
                printf("Cannot start th2, giving up.\n");
                exit(1);
        }
        ret = pthread_create(&th3, NULL, fv3, NULL);
        if (ret != 0) {
                printf("Cannot start th3, giving up.\n");
                exit(1);
        }

        pthread_join(th1, NULL);

        if (0) {
                sleep(1);
        }

        printf("Done\n");

        ret = pthread_cancel(th1);
        switch (ret) {
                case 0:
                        printf("th1 cancelled successfully\n");
                        break;
                case ESRCH:
                        printf("ESRCH while cancelling th1\n");
                        break;
                default:
                        printf("Unknown error: %i\n", ret);
        }

        ret = pthread_cancel(th2);
        switch (ret) {
                case 0:
                        printf("th2 cancelled successfully\n");
                        break;
                case ESRCH:
                        printf("ESRCH while cancelling th2\n");
                        break;
                default:
                        printf("Unknown error: %i\n", ret);
        }

        ret = pthread_cancel(th3);
        switch (ret) {
                case 0:
                        printf("th3 cancelled successfully\n");
                        break;
                case ESRCH:
                        printf("ESRCH while cancelling th3\n");
                        break;
                default:
                        printf("Unknown error: %i\n", ret);
        }

        return 0;
}

Ha van nem várunk semmit "Done" előtt:


fv1: Starting
fv1: Exiting
Done
ESRCH while cancelling th1
th2 cancelled successfully
th3 cancelled successfully

Ha van sleep(1) a "Done" előtt:


fv1: Starting
fv1: Exiting
fv2: Starting
fv2: Exiting
fv3: Starting
fv3: Exiting
Done
ESRCH while cancelling th1
ESRCH while cancelling th2
ESRCH while cancelling th3

Hm, én ezt kicsit másképpen oldottam meg közben. th2, és th3 szálak lefutásának legvégén meghívtam

pthread_cancel(thmásik), pthread_cancel(thén)

függvényeket, azaz fordított sorrendben, így amelyik előbb lefut, az előbb megszünteti a másikat, és utána önmagát is, és jöhet a done.

Azt nem tudom csak, hogy mi van akkor, ha az egyik szál kiadja a másik szál megszüntetésére a

pthread_cancel

- t, szóval az már elkezdődött, de még nem fejeződőtt be, vált az OS, ugyanez történik a másik szállal is. Ilyenkor előfordulhat valami olyan helyzet, ami miatt itt nem menne tovább a progi? Nem kifejezetten holtpontra gondolok.