2010-03-09 19 views
13

Estoy usando bloqueos de lectura/escritura en Linux y he encontrado que intentar actualizar un objeto bloqueado de lectura a un bloqueo de escritura bloquea los bloqueos.pthreads: bloqueos de lector/escritor, actualización del bloqueo de lectura para escribir el bloqueo

decir

// acquire the read lock in thread 1. 
pthread_rwlock_rdlock(&lock); 

// make a decision to upgrade the lock in threads 1. 
pthread_rwlock_wrlock(&lock); // this deadlocks as already hold read lock. 

He leído la página del manual y es bastante específica.

El subproceso de llamada puede interbloqueos si al la vez que se realiza la llamada se mantiene el bloqueo de lectura-escritura (ya sea una lectura o bloqueo de escritura).

¿Cuál es la mejor manera de actualizar un bloqueo de lectura a un bloqueo de escritura en estas circunstancias ... No quiero introducir una carrera en la variable que estoy protegiendo.

Presumiblemente, puedo crear otro mutex para abarcar la liberación del bloqueo de lectura y la adquisición del bloqueo de escritura, pero luego realmente no veo el uso de bloqueos de lectura/escritura. También podría usar simplemente un mutex normal.

Thx

+0

Boost.Thread tiene el concepto UpgradeLockable, pero dudo que te sirva de mucho si tu código ya está en la onda en pthreads. –

+0

@Steve. ¿Sabes cómo se implementa? ¿Utiliza un mutex separado que es lo que estaba considerando hacer? Supongo que podría descargarlo y verificarlo: o) – ScaryAardvark

+0

No, no sé cómo lo hace Boost.Thread, lo siento. –

Respuesta

15

¿Qué más que un bloqueo muerto desea en el siguiente escenario?

  • hilo 1 adquirir bloqueo de lectura
  • rosca 2 adquirir bloqueo de lectura
  • hilo 1 Empezar a actualizar bloqueo para escribir
  • rosca 2 piden actualizar bloqueo para escribir

Así que' Acabo de soltar el bloqueo de lectura, adquirir el bloqueo de escritura y comprobar nuevamente si tengo que hacer la actualización o no.

+0

¿Por qué uno de los hilos obtendría el bloqueo de escritura si el otro tiene un bloqueo de lectura? Y si finalmente ambos pueden obtener el bloqueo de escritura, el segundo tendría el problema de que todas las comprobaciones que se han hecho deben volverse a realizar, ya que el recurso protegido puede haber cambiado de manera significativa. Liberar y readquirir proporciona el mismo comportamiento. – AProgrammer

+0

Esperaba evitar la segunda comprobación del objeto que se está bloqueando. Sé que la implementación de IBM de bloqueos de lectura/escritura permite que un hilo de llamada actualice su bloqueo si es el único hilo que contiene un bloqueo de escritura. http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=/apis/users_93.htm – ScaryAardvark

+0

@nos. Sí, esto sería un punto muerto. T1 cuando se solicita la actualización estaría bloqueado, ya que T2 tiene un bloqueo de lectura. T2 luego se bloquearía al actualizar para escribir el bloqueo ya que T1 tiene un bloqueo de lectura. – ScaryAardvark

0

más fácil y más segura sería la de tomar la escritura de bloqueo desde el momento en que usted podría querer cambiar sus datos en lugar de desde el momento en que está seguro de que va a cambiarlo. Sé que esto hará que el acceso a sus datos sea un poco más serializado.

Estaba un poco sorprendido al leer esta pregunta, porque ni siquiera consideré primero tomar un bloqueo de lectura y luego actualizar a un bloqueo de escritura. Bueno, una situación diferente podría necesitar diferentes enfoques.

+2

Parece un poco excesivo adquirir un bloqueo de escritura cuando no lo necesite. Esto se serializaría, como usted señaló. Mientras que adquirir un bloqueo de lectura no se bloqueará. En el momento en que sabe que necesita cambiar algo, puede actualizar a un bloqueo de escritura. Es solo el acto real de hacerlo, bajo posix, introduce una carrera, lo cual es una pena. – ScaryAardvark

+0

Es una pena, pero en la mayoría de los casos que conozco, es más una diferencia teórica. – stefaanv

0

Creo que en lugar de usar pthread de lectura/escritura, puede usar Posix fcntl(). Aquí puede actualizar de lectura a escritura sin problemas. Lo estamos usando para la inserción de B-tree. Una vez que lleguemos a conocer el nodo donde ocurre la inserción, lo actualizaremos para escribir el bloqueo. Además, cuando necesitemos dividir el nodo, actualizaremos el bloqueo del nodo, su nodo padre y los elementos secundarios de lectura a escritura. Como B-tree es una estructura de datos basada en archivos, ayuda a bloquear la región del archivo.

Cuestiones relacionadas