Praktische Thread-Programmierung
Thread-Synchronisationsmechanismen
Mutex (Mutual Exclusion)
#include <mutex>
#include <thread>
std::mutex shared_mutex;
void critical_section(int thread_id) {
shared_mutex.lock();
// Geschützte kritische Sektion
std::cout << "Thread " << thread_id << " greift auf gemeinsame Ressource zu" << std::endl;
shared_mutex.unlock();
}
Synchronisationstechniken
flowchart TD
A[Thread-Synchronisation] --> B[Mutex]
A --> C[Bedingte Variablen]
A --> D[Atomare Operationen]
A --> E[Semaphoren]
Thread-Pool-Implementierung
#include <thread>
#include <vector>
#include <queue>
#include <functional>
class ThreadPool {
private:
std::vector<std::thread> workers;
std::queue<std::function<void()>> tasks;
std::mutex queue_mutex;
bool stop;
public:
ThreadPool(size_t threads) : stop(false) {
for(size_t i = 0; i < threads; ++i)
workers.emplace_back([this] {
while(true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(this->queue_mutex);
if(this->stop && this->tasks.empty())
break;
if(!this->tasks.empty()) {
task = std::move(this->tasks.front());
this->tasks.pop();
}
}
if(task)
task();
}
});
}
};
Concurrency-Muster
Muster |
Beschreibung |
Anwendungsfall |
Produzent-Konsument |
Threads tauschen Daten aus |
Gepufferte E/A-Operationen |
Leser-Schreiber |
Mehrere Lese-, exklusive Schreibzugriffe |
Datenbankzugriff |
Sperrsynchronisation |
Threads warten an einem bestimmten Punkt |
Parallele Berechnungen |
Erweiterte Thread-Techniken
Bedingte Variablen
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
bool ready = false;
void worker_thread() {
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, []{ return ready; });
// Daten verarbeiten
}
void main_thread() {
{
std::lock_guard<std::mutex> lock(m);
ready = true;
}
cv.notify_one();
}
Thread-Sicherheitstrategien
- Minimierung des gemeinsamen Zustands
- Verwendung unveränderlicher Daten
- Implementierung korrekter Sperren
- Vermeidung verschachtelter Sperren
flowchart TD
A[Thread-Performance] --> B[Minimierung von Kontextwechseln]
A --> C[Optimierung der Threadanzahl]
A --> D[Verwendung von sperrfreien Algorithmen]
A --> E[Reduzierung des Synchronisationsaufwands]
Fehlerbehandlung bei Multithreading
#include <stdexcept>
void thread_function() {
try {
// Thread-Logik
if (fehlerbedingung) {
throw std::runtime_error("Thread-Fehler");
}
} catch (const std::exception& e) {
// Thread-spezifische Ausnahmen behandeln
std::cerr << "Thread-Fehler: " << e.what() << std::endl;
}
}
LabEx-Best Practices für Multithreading
- Verwendung der Standardbibliothek für Thread-Unterstützung
- Vorzugsweise Verwendung von Abstraktionen höherer Ebene
- Gründliche Tests
- Überwachung der Ressourcenverwendung
Häufige Fallstricke beim Multithreading
Fallstrick |
Lösung |
Wettlaufbedingungen |
Verwenden Sie Mutexe, atomare Operationen |
Deadlocks |
Implementieren Sie eine Sperrreihenfolge |
Ressourcenkonkurrenz |
Minimieren Sie kritische Abschnitte |