creo que tenes un problema con la clase mutex
en general, las clases mutex, thread, socket etc tiene el constructor de
copia oculto (privado) al igual que el operador =
eso te permite no equivocarte copiando mutex por ejemplo
dicho eso:
class Lock {
public:
Lock(Mutex &mutex):mutex(mutex){
this->mutex.lock();
}
~Lock(){
mutex.unlock();
}
private:
Mutex mutex;
};
fijate que tu atributo es un objeto Mutex y en el contructor de Lock estas
haciendo una copia
"Lock(Mutex &mutex):mutex(mutex){...}"
para arreglar esto, me parece que basta con poner el atributo mutex como
*referencia* (Mutex &mutex)
para entrar en detalle...
cuando creas el lock, el mutex se hace unlock al destruirse
void * run() {
std::cout << "thread init " << n << std::endl;
std::cout << "thread locked " << n << std::endl;
{
Lock lock(*this->barrier->getMutex());
std::cerr << "thread " << n << " address: " <<
this->barrier->getMutex() << std::endl;
std::cout << "thread unlocked " << n << std::endl;
for (int i=0; i<80;i++) {
std::cout << n;
usleep(10000);
}
std::cout << std::endl;
}
return 0;
}
cuando pones "std::cout << "thread unlocked " << n << std::endl;", el lock
se libera despues del "}" posterior al usleep, no antes
fijate que con cada hilo que instancias y le haces un run, se crea un Lock
por hilo
pero como el Lock esta copiando el mutex (no es referencia), es como que
cada hilo tiene un mutex
al no tener un mutex en comun es como si los mutex no existieran porque
ningun hilo bloquea al otro
quizas me equivoque, pero si corregis el problema de la referencia, te
deberia listar todos 1, y despues todos 2
porque el for esta dentro de la zona de codigo critico
con esto no ganas nada (es lo mismo que hayas ejecutado dos veces la misma
funcion desde un unico hilo)
si la idea es ver como el scheduler de threads va rotando de hilo en
ejecucion, pone el lock dentro del for para proteger la parte de la
impresion
ademas, tenes el usleep dentro del codigo protegido por el Lock, con lo que
no ganas nada (el sleep no provoca cambio de ejecucion de thread, solo un
retraso en el hilo)
la direccion que imprime del mutex es siempre la misma porque la sacas del
Lockeable, pero por dentro de cada Lock tiene su propio mutex
saludos
--------------------------------------------------
From: "Carlos Pantelides" <[EMAIL PROTECTED]>
Sent: Tuesday, April 29, 2008 1:00 PM
To: "Una lista para consultas deprogramacin" <[email protected]>
Subject: [Prog] Inconveniente por concurrencia
Hola todos/as:
Estoy teniendo un inconveniente de concurrencia.
Envio el código, que es mucho mas claro que cualquier
cosa que pueda decir
Gracias anticipadas por cualquier ayuda o
recomendación.
Carlos Pantelides
----------salida--------------
main address: 0x603030
thread init 1
thread locked 1
thread 1 address: 0x603030
thread unlocked 1
1thread init 2
thread locked 2
thread 2 address: 0x603030
thread unlocked 2
2Los threads no debieron haber dicho thread unlocked
12121212121212121212121212121212121212121212121212121212121212121212121221121212121212121212121212121221212121211212121212121212121212121212212121212121211212
fin
----------codigo--------------
#include <pthread.h>
#include <iostream>
class Mutex {
public:
Mutex() { pthread_mutex_init(&mutex, 0); }
void lock() { pthread_mutex_lock(&mutex); }
void unlock(){ pthread_mutex_unlock(&mutex);}
~Mutex() { pthread_mutex_destroy(&mutex); }
private:
pthread_mutex_t mutex;
};
class Lock {
public:
Lock(Mutex &mutex):mutex(mutex){
this->mutex.lock();
}
~Lock(){
mutex.unlock();
}
private:
Mutex mutex;
};
class Thread {
public:
Thread() { last_error=0; }
virtual ~Thread() {};
int start() {
return last_error = pthread_create(&thread, 0,
start_routine, this);};
void * join(){
void * result;
last_error = pthread_join(thread, &result);
return result;
};
protected:
virtual void * run()=0;
int last_error;
private:
pthread_t thread;
static void * start_routine(void * arg){
Thread * r = (Thread *) arg;
void * result;
result = r->run();
return result;
};
};
class Lockeable {
public:
Lockeable() { mutex = new Mutex(); }
Mutex * getMutex() { return mutex; }
~Lockeable() { delete(mutex); }
private:
Mutex * mutex;
};
class Ejemplo: public Thread {
public:
Ejemplo(Lockeable * barrier, int n) {
this->barrier=barrier;
this->n =n;
}
protected:
void * run() {
std::cout << "thread init " << n << std::endl;
std::cout << "thread locked " << n << std::endl;
{
Lock lock(*this->barrier->getMutex());
std::cerr << "thread " << n << " address: " <<
this->barrier->getMutex() << std::endl;
std::cout << "thread unlocked " << n << std::endl;
for (int i=0; i<80;i++) {
std::cout << n;
usleep(10000);
}
std::cout << std::endl;
}
return 0;
}
private:
bool ok;
int n;
Lockeable * barrier;
};
int main(int argc, char ** argv) {
Lockeable * barrier = new Lockeable();
Ejemplo t1(barrier,1);
Ejemplo t2(barrier,2);;
{
Lock lock(*barrier->getMutex());
std::cerr << "main address: " << barrier->getMutex()
<< std::endl;
t1.start();
t2.start();
std::cout << "Los threads no debieron haber dicho
thread unlocked" << std::endl;
}
t1.join();
t2.join();
std::cout << "fin" << std::endl;
return 0;
}
____________________________________________________________________________________
Be a better friend, newshound, and
know-it-all with Yahoo! Mobile. Try it now.
http://mobile.yahoo.com/;_ylt=Ahu06i62sR8HDtDypao8Wcj9tAcJ
_______________________________________________
Lista de correo Programacion.
[email protected]
http://listas.fi.uba.ar/mailman/listinfo/programacion
No virus found in this incoming message.
Checked by AVG.
Version: 8.0.100 / Virus Database: 269.23.6/1403 - Release Date:
29/04/2008 07:26 a.m.
__________________________________________________
Correo Yahoo!
Espacio para todos tus mensajes, antivirus y antispam ¡gratis!
¡Abrí tu cuenta ya! - http://correo.yahoo.com.ar
_______________________________________________
Lista de correo Programacion.
[email protected]
http://listas.fi.uba.ar/mailman/listinfo/programacion