2017-12-17 18 views
-1

So habe ich ein Problem: Wenn ich versuche, den letzten Thread zu erstellen, heißt es immer, dass Kern ausgegeben wird. Es macht nichts, wenn ich schreibe, um 5 oder 2 Threads zu erstellen. Hier ist mein Code: UPD: Jetzt kann ich nicht mehr als 3 Threads und Threads tun nicht Funktionen, die ich will sie tun (konsumieren und produzieren)"Segmentierungsfehler (Core Dumped)" bei der Verwendung von Pthread_create

UPD_2: Jetzt habe ich eine Nachricht wie gehen dass: terminate nach dem werfen einer Instanz ‚genannt rekursiv aufgerufen terminate rekursiv Aborted (core dumped)

#include<cstdlib> 
#include <iostream> 
#include <string> 
#include <mutex> 
#include <pthread.h> 
#include <condition_variable> 

#define NUM_THREADS 4 

using namespace std; 

struct thread_data 
{ 
    int thread_id; 
    int repeat; 
}; 


class our_monitor{ 
    private: 
     int buffer[100]; 
     mutex m; 
     int n = 0, lo = 0, hi = 0; 
     condition_variable in,out; 
     unique_lock<mutex> lk; 

    public: 
     our_monitor():lk(m) 
     { 

     } 
     void insert(int val, int repeat) 
     { 
      in.wait(lk, [&]{return n <= 100-repeat;}); 
      for(int i=0; i<repeat; i++) 
      { 
       buffer[hi] = val; 
       hi = (hi + 1) % 100;  //ring buffer 
       n = n +1;   //one more item in buffer 
      } 
      lk.unlock(); 
      out.notify_one(); 
     } 

     int remove(int repeat) 
     { 
      out.wait(lk, [&]{return n >= repeat;}); 
      int val; 
      for(int i=0; i<repeat; i++) 
      { 
       val = buffer[lo]; 
       lo = (lo + 1) % 100; 
       n -= 1; 
      } 
      lk.unlock(); 
      in.notify_one(); 
      return val; 
     } 
}; 

our_monitor mon; 

void* produce(void *threadarg) 
{ 
    struct thread_data *my_data; 
    my_data = (struct thread_data *) threadarg; 
    cout<<"IN produce after paramiters"<< my_data->repeat<<endl; 
    int item; 
    item = rand()%100 + 1; 
    mon.insert(item, my_data->repeat); 
    cout<< "Item: "<< item << " Was prodused by thread:"<< my_data->thread_id << endl; 
} 

void* consume(void *threadarg) 
    { 
     struct thread_data *my_data; 
     my_data = (struct thread_data *) threadarg; 
     cout<<"IN consume after paramiters"<< my_data->repeat<<endl; 
     int item; 
     item = mon.remove(my_data->repeat); 
     if(item) cout<< "Item: "<< item << " Was consumed by thread:"<< my_data->thread_id << endl; 
    } 

int main() 
{ 
    our_monitor *mon = new our_monitor(); 
    pthread_t threads[NUM_THREADS]; 
    thread_data td[NUM_THREADS]; 
    int rc; 
    int i; 

    for(i = 0; i < NUM_THREADS; i++) 
    { 
     td[i].thread_id = i; 
     td[i].repeat = rand()%5 + 1; 
     if(i % 2 == 0) 
     { 
      cout << "main() : creating produce thread, " << i << endl; 
      rc = pthread_create(&threads[i], NULL, produce, (void*) &td[i]); 

      if (rc) 
      { 
       cout << "Error:unable to create thread," << rc << endl; 
       exit(-1); 
      } 
     } else 
     { 
      cout << "main() : creating consume thread, " << i << endl; 
      rc = pthread_create(&threads[i], NULL, consume, (void *)&td[i]); 

      if (rc) 
      { 
       cout << "Error:unable to create thread," << rc << endl; 
       exit(-1); 
      } 
     } 
    } 
    pthread_join(threads[0], NULL); 
    pthread_join(threads[1], NULL); 
    pthread_join(threads[2], NULL); 
    //pthread_exit(NULL); 

} 

UPD genannt terminate: Jetzt kann ich nicht mehr tun, als 3 Fäden und Fäden nicht Funktionen tun dass ich möchte, dass sie tun (konsumieren und produzieren)

UPD_2: Jetzt eine Nachricht wie die, dass ich gehen habe: enden nach dem Werfen einer Instanz ‚genannt rekursiv rekursiv Aborted (core dumped)

+0

Woher wissen Sie, dass es in "Haupt" eher als einer der Thread-Procs fällt? –

+1

Können Sie erklären, zu welchen Funktionen 'produzieren',' konsumieren'? –

+0

Ich bearbeite meine Frage, es gibt vollen Code –

Antwort

0

Von cppref über std :: condition_variable.wait (...)

"Der Aufruf dieser Funktion, wenn lock.mutex() durch den aktuellen Faden nicht gesperrt ist nicht definiertes Verhalten."

http://en.cppreference.com/w/cpp/thread/condition_variable/wait

Leider wird das Programm nicht auf Linie abstürzen 47, aber auf der Linie 55, wo Sie das Schloss entriegeln, die nicht gesperrt wurde.

enter image description here

enter image description here

Versperren Sie das Schloss, wenn Sie Ihre Funktionen eingeben. Ich habe den Rest Ihrer Logik schnell überprüft, und ich bin zu 85% sicher, dass es sonst in Ordnung ist.

Während ich dich hier habe, ist das nicht unbedingt notwendig, aber es ist eine gute Übung. std :: lock_guard und std :: unique_lock sperren den Mutex automatisch, wenn er in den Bereich eintritt und entsperrt ihn, wenn er den Bereich verlässt. Dies hilft bei der Vereinfachung der Ausnahmebehandlung und der Rückgabe merkwürdiger Funktionen. Ich empfehle Ihnen, lk als Member-Variable loszuwerden und stattdessen als lokale Variable zu verwenden.

void insert(int val, int repeat) 
    { 
     { // Scoped. Somewhat pedantic in this case, but it's always best to signal after the mutex is unlocked 
      std::unique_lock<std::mutex> lk(m); 
      in.wait(lk, [&]{return n <= 100-repeat;}); 
      for(int i=0; i<repeat; i++) 
      { 
       buffer[hi] = val; 
       hi = (hi + 1) % 100;  //ring buffer 
       n = n +1;   //one more item in buffer 
      } 
     } 
     out.notify_one(); 
    } 

Ok, jetzt für die letzte Ausgabe. Das Coole an Produzenten/Konsumenten ist, dass wir gleichzeitig produzieren und konsumieren können. Wir haben jedoch gerade unsere Funktionen gesperrt, so dass dies nicht mehr möglich ist.Was Sie jetzt tun können, ist Ihr Zustand Sperre/wait/unlock/Arbeit/Signal innerhalb der for-Schleife bewegen

in Pseudo-Code:

// produce: 
while (true) 
{ 
    { 
     unique_lock lk(m) 
     wait(m, predicate) 
    } 
    produce 1 
    signal 
} 

Die zur Verwendung von Semaphoren entspricht (die C++ 11 stl nicht haben, aber Sie können leicht Ihr eigenes wie oben gezeigt.)

// produce: 
semaphore in(100); 
semaphore out(0); 
while (true) 
{ 
    in.down(1) // Subtracts 1 from in.count. Blocks when in.count == 0 (meaning the buffer is full) 
    produce 1 
    out.up(1) // Adds 1 to out.count 
} 
0

Wenn main Ende genannt terminate genannt beenden, geht td out of scope und hört auf zu existieren. Aber Sie haben in Threads darauf hingewiesen. Sie müssen sicherstellen, dass td weiterhin vorhanden ist, solange es von Threads verwendet wird.

+0

wie kann ich das tun? –

+0

@MaxPan Eine der möglichen Möglichkeiten: Verbindung mit den Threads am Ende von 'main', so dass Threads mit der Zeit beendet wurden, dass' td' aus dem Geltungsbereich verschwunden ist. –

+0

Ein häufiges Muster ist die Zuweisung einer Struktur, um Daten an einen Thread mit 'new' zu übergeben. Übergeben Sie den Thread den Zeiger, den Sie von 'new' erhalten haben. Nachdem der Thread die Daten gelesen hat, kann er sie löschen. Das funktioniert jedoch nicht, wenn Sie Daten aus dem Thread zurückgeben müssen. –

Verwandte Themen