QThread wann und wie locken ?
Verfasst: 9. Juli 2008 10:10
Hallo,
ich beschäftige mich schon eine weile mit QT und habe eine Serveranwendung geschrieben welche auch im Grunde funktioniert.
Jedoch werde ich nicht ganz schlau wann ich was wo locken muss.
Und vorallem dem mit welchem Lock.
Ich habe mal ein Beispiel Code mitgegeben, der aktuell zeigt wo ich logge.
Nämlich im Object welches von meheren Threads modifiziert wird über die setter Methoden.
Fragen :
a) Könnt ihr euch das mal anschauen und mir Verbesserungsvorschläge schicken?
b) Kennt ihr ein gutes Buch über C++ und MultiThreadding?
c) Muss ich auch die privaten variablen eines Threads schützen ?
Bis jetzt habe es so verstanden, das ich nur ein mutex etc. benötige
wenn ich eine variable von mehreren Threads modifiziere.
d) Wenn ich von einer Klasse mehrere Threads anlege, sind die privaten variablen thread-safe ?
Hier mal mein Beispielcode
Definition Task :
Implementierung Task :
Server Komponente :
Besteht aus mehreren Worker Threads und einem Dispatcher Thread (eigene Klassen).
Stellt darüber hinaus Klassen zum lesen von Configfiles, logging etc bereit.
Hier der Beispielablauf eines Arbeitsvorgangs:
Dispatcher-Thread #1:
a) Datenbank lesen
b) neues OPbject der Klasse Task erzeugen.
z.B.
c) Schauen wie viele Worker Threads arbeiten und solange kein Thread frei ist, warten.
d) Wenn worker frei : Signal newTask absetzen mit pointer auf Task-Object
Server Komponete :
a) Task-Object klassifizieren und an geeigneten Worker-Thread vermitteln
b) newTask Signal wird per QueuedConnection zu einem freien Worker-Thread geschickt
Worker Thread #1:
a) Auftrag annehmen unter Verwendung des pointers auf taskObj:
Signal progressTask absetzen.
Server Komponete :
a) Signal progressTask per QueuedConnection an den Dispatcher-Thread #1 weiterleiten
Dispatcher-Thread #1:
a) Status ermitteln
b) Alten status aus der Datenbankk emitteln
c) Status updaten
Worker Thread #1:
b) Auftrag abarbeiten
c) ggf Status korrigieren wie a)
d) Auftrag erledigt
c) Status auf "done" stellen unter Verwendung a)
Dispatcher-Thread #1:
Reihenfolge a), b), c) ermitteln
d) Auftrag intern als "done" markieren und taskObj löschen
ich beschäftige mich schon eine weile mit QT und habe eine Serveranwendung geschrieben welche auch im Grunde funktioniert.
Jedoch werde ich nicht ganz schlau wann ich was wo locken muss.
Und vorallem dem mit welchem Lock.
Ich habe mal ein Beispiel Code mitgegeben, der aktuell zeigt wo ich logge.
Nämlich im Object welches von meheren Threads modifiziert wird über die setter Methoden.
Fragen :
a) Könnt ihr euch das mal anschauen und mir Verbesserungsvorschläge schicken?
b) Kennt ihr ein gutes Buch über C++ und MultiThreadding?
c) Muss ich auch die privaten variablen eines Threads schützen ?
Bis jetzt habe es so verstanden, das ich nur ein mutex etc. benötige
wenn ich eine variable von mehreren Threads modifiziere.
d) Wenn ich von einer Klasse mehrere Threads anlege, sind die privaten variablen thread-safe ?
Hier mal mein Beispielcode
Definition Task :
Code: Alles auswählen
class Task {
public:
Task();
//getters and setters
quint64 getID();
void setID(quint64 _id);
QString getStatus();
void setStatus(QString _status);
private:
quint64 ID;
QString status;
}
Code: Alles auswählen
/*
* Ctor Task object
* Fill in initial default values
*/
Task::Task() {
mutex = new QMutex();
this->ID = 0;
}
quint64 Task::getID() {
return this->ID;
}
void Task::setID(quint64 _id) {
mutex->lock();
this->ID = _id;
mutex->unlock();
}
QString Task::getStatus() {
return this->Status;
}
void Task::setStatus(QString _status) {
mutex->lock();
this->Status = _status;
mutex->unlock();
}
Server Komponente :
Besteht aus mehreren Worker Threads und einem Dispatcher Thread (eigene Klassen).
Stellt darüber hinaus Klassen zum lesen von Configfiles, logging etc bereit.
Hier der Beispielablauf eines Arbeitsvorgangs:
Dispatcher-Thread #1:
a) Datenbank lesen
b) neues OPbject der Klasse Task erzeugen.
z.B.
Code: Alles auswählen
Task taskObj = new Task();
taskObj->setID(Datebankwert);
c) Schauen wie viele Worker Threads arbeiten und solange kein Thread frei ist, warten.
d) Wenn worker frei : Signal newTask absetzen mit pointer auf Task-Object
Server Komponete :
a) Task-Object klassifizieren und an geeigneten Worker-Thread vermitteln
b) newTask Signal wird per QueuedConnection zu einem freien Worker-Thread geschickt
Worker Thread #1:
a) Auftrag annehmen unter Verwendung des pointers auf taskObj:
Code: Alles auswählen
taskObj = _task; //_task pointer to task object
taskObj->setStatus("progress");
Server Komponete :
a) Signal progressTask per QueuedConnection an den Dispatcher-Thread #1 weiterleiten
Dispatcher-Thread #1:
a) Status ermitteln
Code: Alles auswählen
QString status = taskObj->getStatus();
Code: Alles auswählen
oldStatus = query.value(0).toString();
Code: Alles auswählen
if (status != oldStatus()) {
query.exec("UPDATE ....");
};
Worker Thread #1:
b) Auftrag abarbeiten
c) ggf Status korrigieren wie a)
d) Auftrag erledigt
c) Status auf "done" stellen unter Verwendung a)
Dispatcher-Thread #1:
Reihenfolge a), b), c) ermitteln
d) Auftrag intern als "done" markieren und taskObj löschen
Code: Alles auswählen
delete taskObj;