POSIX Mutex

Nel post precedente abbiamo visto come gestire diversi thread in una applicazione scritta in C++. Ora vediamo come gestire i problemi di concorrenza, sempre nell'ambito delle specifiche POSIX.

Il concetto di semaforo viene implementato con il Mutex (che sta per mutual exclusion, mutua esclusione).

Dovrebbe servire a spiegare il concetto questo esempio.

Scriviamo una piccola applicazione in cui una classe somma dei dati contenuti al suo interno dividendo il lavoro su quattro thread. Il punto da tenere sotto controllo é dove viene letto e incrementato il totale corrente, che risulta essere la risorsa condivisa tra i diversi thread.

Infatti si regolamentasse il suo accesso con un mutex, potrebbe succedere che un thread legga il suo valore dopo di un altro ma scriva il suo risultato aggiornato prima. Di conseguenza il suo lavoro andrebbe perso.

Vediamo il codice:
#include <errno.h>
#include <iostream>
#include <sstream>

using namespace std;

class HugeWork {
public:
HugeWork(int res, int a, int b, int c, int d) : m_result(res) {
m_values[0] = a;
m_values[1] = b;
m_values[2] = c;
m_values[3] = d;

pthread_mutex_init(&m_mutex, 0);
}

~HugeWork() {
pthread_mutex_destroy(&m_mutex);
}

double getResult();
private:
static void* increase(void*);

int m_result;
int m_values[4];

pthread_t m_thread_id[4];
pthread_mutex_t m_mutex;
};

double HugeWork::getResult() {
ostringstream os;
for (int i = 0; i < 4; ++i) {
if (pthread_create(&m_thread_id[i], NULL, &increase, this) < 0) {
cout << "Error creating thread " << i << ": " << errno << endl;
return 0;
}

os << "Thread " << m_thread_id[i] << " created (" << i << ")" << endl;
cout << os.str();
os.str("");
}

// wait for all the threads to complete
for(int i = 0; i < 4; ++i) {
os << "Joining thread " << m_thread_id[i] << endl;
cout << os.str();
os.str("");

pthread_join(m_thread_id[i], 0);
}

return m_result;
};

// notice: should be static for pthread requirements
void* HugeWork::increase(void* ptr) {
HugeWork* hw = static_cast<HugeWork*> (ptr);


sleep(1);

int result = 0;
for (int i = 0; i < 4; ++i) {
result += hw->m_values[i];
}

pthread_mutex_lock(&hw->m_mutex);
cout << "increasing " << result << endl;
hw->m_result += result;
pthread_mutex_unlock(&hw->m_mutex);

return 0;
}

int main(int argc, char** argv) {
HugeWork hw(1, 1, 2, 3, 4);

cout << "Final result: " << hw.getResult() << endl;
}

Nessun commento:

Posta un commento