Frage

Ich habe 2 Threads und globale Queue, ein Thread (T1) schieben, die Daten und ein anderen (T2) erscheint, die Daten, wollte ich diese Operation synchronisieren, ohne Funktion, wo wir diese Warteschlange mit kritischem Abschnitt mit dem Windows-API verwenden können .

Die Queue ist global, und ich wollte synchron wissen, wie wird es durch Sperren Adresse Queue getan?.

Die Antworten werden sehr geschätzt werden. :)

Ist es möglich, Boost-Bibliothek für das oben beschriebene Problem zu benutzen?

Danke

War es hilfreich?

Lösung

Ein Ansatz ist, zwei Warteschlangen zu haben, statt ein:

  • Der Hersteller Thread Schübe Elemente Warteschlange A.
  • Wenn der Verbraucher Thread will Artikel Pop, Warteschlange A mit leerer Warteschlange B ausgetauscht wird.
  • Der Produzent Thread weiterhin Elemente in die neue Warteschlange A drücken.
  • Der Verbraucher, ohne Unterbrechung, verbraucht Elemente aus Warteschlange B und leert es.
  • Warteschlange A wird mit Queue B vertauscht etc.

Die einzige Verriegelung / Blockierung / Synchronisation geschieht, wenn die Warteschlangen getauscht werden, was eine schnelle Operation sein sollte, da es ist wirklich eine Frage zwei Zeiger von Swapping.

Andere Tipps

Vielleicht haben Sie eine Warteschlange mit diesen Bedingungen machen könnten, ohne alle keine atomics oder jeden Thread-sicher Sachen an?

wie wenn es nur ein Kreis Puffer, ein Thread steuert der Lesezeiger und die andere steuert der Schreibzeiger. beide nicht aktualisieren, bis sie fertig Lesen oder Schreiben sind. und es funktioniert?

der einzige Punkt, der Schwierigkeit kommt mit der Bestimmung, wenn == Schreib lesen, ob die Warteschlange voll oder leer ist, aber man kann dies überwinden, indem nur immer ein Dummy-Element mit in der Warteschlange

class Queue
{
     volatile Object* buffer;
     int size;
     volatile int readpoint;
     volatile int writepoint;

     void Init(int s)
     {
          size = s;
          buffer = new Object[s]; 
          readpoint = 0;
          writepoint = 1;
     }

     //thread A will call this
     bool Push(Object p)
     {
         if(writepoint == readpoint)
         return false;
         int wp = writepoint - 1;
         if(wp<0)
             wp+=size;
         buffer[wp] = p;
         int newWritepoint = writepoint + 1;
         if(newWritepoint==size)
            newWritePoint = 0;
         writepoint = newWritepoint;
         return true;
      }

      // thread B will call this
      bool Pop(Object* p)
      {
          writepointTest = writepoint;
          if(writepointTest<readpoint)
               writepointTest+=size;
          if(readpoint+1 == writepoint)
              return false;
          *p = buffer[readpoint];

         int newReadpoint = readpoint + 1;
         if(newReadpoint==size)
            newReadPoint = 0;
         readpoint = newReadPoint;
         return true;
      }
};

Eine weitere Möglichkeit, um dieses Problem zu umgehen ist die Warteschlange dynamisch zuzuweisen und es zu einem Zeiger zuweisen. Der Zeigerwert wird zwischen Threads ausgab, wenn Elemente werden aus der Warteschlange entfernt, und Sie schützen diese Operation mit einem kritischen Abschnitt. Das bedeutet für jeden Stoß in die Warteschlange sperren, aber viel weniger Streit über die Beseitigung der Elemente.

Das funktioniert gut, wenn Sie viele Elemente zwischen Einreihen und Warteschlangenauflösungs haben, und arbeitet weniger gut mit wenigen Artikeln.

Beispiel (ich verwende einige gegeben RAII Verriegelungs Klasse die Verriegelung zu tun). Auch Anmerkung ... wirklich nur sicher, wenn nur ein Thread Warteschlangenauflösungs.

queue* my_queue = 0;
queue* pDequeue = 0;
critical_section section;

void enqueue(stuff& item)
{
   locker lock(section);
   if (!my_queue)
   {
      my_queue = new queue;
   }
   my_queue->add(item);
}

item* dequeue()
{
   if (!pDequeue)
   {  //handoff for dequeue work
      locker lock(section);
      pDequeue = my_queue;
      my_queue = 0;
   }
   if (pDequeue)
   {
      item* pItem = pDequeue->pop(); //remove item and return it.
      if (!pItem)
      {
         delete pDequeue;
         pDequeue = 0;
      }
      return pItem;
   }
   return 0;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top