threads - cond var



  • Ich habe 3 Threads (thermo, druck, feuchtigk).
    Thread thermo 1 sek warten, rand. zahl ermitteln und in file schreiben
    Thread druck 2 sek warten, rand. zahl ermitteln und in file schreiben
    thread feuchtig 3 sek warten, rand. zahl ermitteln und in file schreiben

    In der File soll immer thermo, druck, feuchtig stehen; dh. die Werte die zwischen drinnen ermittelt werden (wo nicht geschrieben werden soll) sollen verworfen werden.

    Jetzt habe ich es versucht, indem ich eine globale Variable deklariert hab und sie mit mutex gesperrt hab und abgefragt hab ob der Thread schreiben kann oder net. Aber das klappt net wirklich ... ich sollte mit der cond. var arbeiten oder? Aber ich versteh die nicht wirklich.
    Warum funktioniert das mit dem mutex nicht?
    Wie kann ich hier die cond. var. verwenden?

    typedef struct messdaten MDaten;
    
    struct messdaten {
    	time_t time;
    	int wert;
    }__attribute__((__packed__));
    
    void srand(unsigned int seed );
    int rand(void);
    
    FILE *output;
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    
    int count = 0;
    
    void *humidity(void *data)
    {
    	MDaten *humid;
    	int i=15;
    	while(i!=0)
    	{
    		sleep(3);
    		srand((unsigned int) time(NULL));
    		humid->wert = rand() % 100;
    		humid->time = time (NULL);
    		pthread_mutex_lock(&mutex);
    		if(count==2)
    		{
    			fprintf(output,"%d Humidity: %d \n",humid->time,humid->wert);
    			count=0;
    		}
    		pthread_mutex_unlock(&mutex);
    		i--;
    	}
    }
    
    void *temperature(void *data)
    {
    	MDaten *temp;
    	int i=5;
    	while(i!=0)
    	{
    		sleep(1);
    		srand((unsigned int) time(NULL));
    		temp->wert = rand() % 51;
    		temp->time = time (NULL);
    		pthread_mutex_lock(&mutex);
    		if(count==0)
    		{
    			fprintf(output,"%d Temperature: %d °C\n",temp->time,temp->wert);
    			count=2;
    		}
    		pthread_mutex_unlock(&mutex);
    		i--;
    	}
    
    }
    
    int main(int argc, char *argv[])
    {
    	pthread_mutex_init(&mutex,NULL);
    
    	if((!(output = fopen(argv[1], "w+"))))
    	{
    		printf("Error beim öffnen der Ausgabedatei\n");
    	}
    
    	pthread_t temperatur;
    	pthread_t luftfeuchtigkeit;
    	pthread_t luftdruck;
    
    	pthread_create(&temperatur,NULL,temperature,NULL);
    	pthread_create(&luftfeuchtigkeit,NULL,humidity,NULL);
    	//pthread_create(&luftdruck,NULL,air_pressure,NULL);
    
    	pthread_join(temperatur,NULL);
    	pthread_join(luftfeuchtigkeit,NULL);
    	//pthread_join(luftdruck,NULL);
    	fclose(output);
    	return 0;
    
    }
    

    LG



  • Hallo,

    movco schrieb:

    Jetzt habe ich es versucht, indem ich eine globale Variable deklariert hab und sie mit mutex gesperrt hab und abgefragt hab ob der Thread schreiben kann oder net. Aber das klappt net wirklich ...

    und was klappt nicht?

    Vermutlich sind deine i Variable sowas von schnell auf Null, bevor igendwas klappen kann.
    Ich habe zurzeit nichts linuxioides parat, darum habe ich das Prinzip mit Winschlau Threads nachgebaut:

    #include <stdio.h>
    #include <signal.h>
    #include <process.h>  
    #include <windows.h>
    
    // Wir wollen keinen Mutex und auch kein Bitsalat.
    volatile sig_atomic_t order = 'a'; // Schreibzugriff von für Thread A freischalten.
    
    void A(void* p)
    {
    	while(1) 
    	{
    		Sleep(1000);
    		if ( order == 'a' )
    		{
    			puts("a written");
    			order = 'b'; // Schreibzugriff von für Thread B freischalten.
    		}
    		else
    		{
    			puts ("a dropped");
    		}
    	}
    }
    
    void B(void* p)
    {
    	while(1)
    	{
    		Sleep(2000);
    		if ( order == 'b' )
    		{
    			puts("b written"); 
    			order = 'c'; // Schreibzugriff von für Thread C freischalten.
    		}
    		else
    		{
    			puts("b dropped");
    		}
    	}
    }
    
    void C(void* p)
    {
    	while(1)
    	{
    		Sleep(3000);
    		if ( order == 'c' )
    		{
    			puts("c written");
    			order = 'a'; // Schreibzugriff von für Thread A freischalten.
    		}
    		else
    		{
    			puts("c dropped");
    		}
    	}
    }
    
    int main()
    {	
    	puts("Hit enter to start, hit enter to quit.");
    	getchar();
    
    	_beginthread( A, 0, 0 );
    	_beginthread( B, 0, 0 );
    	_beginthread( C, 0, 0 );
    
    	getchar();
    	return 0;
    }
    

    Wozu eigentlich Threads?
    Ist doch hier irgendwie Ressourcenverschwendung. 😕
    💡 Die Werte kann man doch auch nacheinander in eine Datei schreiben. 💡

    Gruß,
    B.B.



  • Ja, threads ist halt die Aufgabenstellung, sonst würde ich die da auch nicht angreifen :).

    Also was bei dem was ich gepostet hab nicht funktioniert, weiß ich selbst nicht genau.
    Ich bekomme einen segfault, ab da wo ich 2 threads gleichzeitig laufen lasse.
    Die threads einzeln laufen schön durch, nur gemeinsam bekomme ich einen segfault.

    Meinen code habt ihr ja 🙂 ... dritter thread ist halt fast gleiche funktion.

    Das i lauft nicht zu schnell runter, zum. erzeugt das keinen segfault :).

    LG



  • Dieser Thread wurde von Moderator/in rüdiger aus dem Forum ANSI C in das Forum Linux/Unix verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Und wenn du da mal ein getchar() vor fclose(output) machst, damit main nicht durchrauscht?



  • Hallo

    Also der Grund für den Segmentation Fault ist einfach: Die Variablen
    MDaten *humid;
    MDaten *temp;
    sind nicht initialisierte Pointer und die zeigen (n)irgend wo hin.
    Du kannst diese Variablen - nachdem sie ohnehin unabhängig von äußeren Einflüssen sind - entweder auf dem Stack anlegen (also MDaten humid; MDaten temp; ) oder auf dem Heap allokieren mit MData *humid = (MData*)malloc(sizeof(MData)); ... natürlich am Ende des Threads nicht auf free(humid); vergessen 😉 !

    Wo du in diesem Beispiel conditional Variablen einsetzen willst, kann ich so nicht ganz nachvollziehen.

    Das wäre nur sinnvoll wenn du eine globale MDaten-Variable hättest. Einige Threads würden dann neue Daten ermitteln, diese geschützt in die globale Variable schreiben und dann zB. einem darauf wartenden weiteren Thread signalisieren, dass er diese Daten in ein File schreiben soll. Das könnte etwa so aussehen

    pthread_mutex_t global_mutex;
    pthread_cont_t global_cond;
    MDaten global_daten;
    
    void thread_read1(void * data)
    {
      ...
      while(...)
      {
        pthread_mutex_lock(&globalmutex);
        ...  // global_daten geschützt manipulieren;
        pthread_cond_signal(&globalmutex, &globalcond); // wartenden thread benachrichtigen
        ...
        pthread_mutex_unlock(&globalmutex);
        ...
      }
      ...
    }
    
    void thread_write(void * data)
    {
      ...
      pthread_mutex_lock(&global_mutex);
      ...
      while(...)
      {
        ...
        pthread_cond_wait(&global_cond, &global_mutex);
        ... // global_daten jetzt geschützt lesen und zB in ein File schreiben
      }
      ...
      pthread_mutex_unlock(&global_mutex);
      ...
    }
    

    Das Geheimnis von pthread_cond_wait ist, dass es den übergebenen Mutex entsperrt und dann solange blockiert bis ein anderer Thread pthread_cond_signal auslöst. Dann wird der Mutex nämlich wieder gesperrt (sobald der andere Thread ihn wieder freigegeben hat).

    mfG XOR 😉



  • Ok danke, gut werde das mit dem Struct gleich anschauen.

    Bzgl. cond_wait:
    Das es den mutex bis zum signal entsperrt habe ich verstanden. Aber wie kann ich mit den cond variable einen Thread direkt ansprechen?

    LG



  • Aber wie kann ich mit den cond variable einen Thread direkt ansprechen?

    Wie meinst du denn 'direkt ansprechen'?
    Wenn du genau einen Thread hast, der mit pthread_cond_wait oder pthread_cond_timedwait auf ein Signal wartet, dann wird genau dieser Thread aufgeweckt. Nur wenn du mehrere Threads einsetzt, die pthread_cond_wait aufrufen, dann wecket pthread_cond_signal genau einen Thread auf (der Scheduler entscheidet welchen ... ist für uns also zufällig) und pthread_cond_broadcast weckt alle gerade wartenden Threads auf.

    Bei n signal-Threads und 1 wait-Thread sprichst du immer den wait-Thread an und der Mutex garantiert dir, dass die Änderungen des signalisierenden Threads im wartenden Thread problemlos zur Verfügung stehen.

    lg XOR 😉


Anmelden zum Antworten