2010-01-18 21 views

Respuesta

28

en lugar del objeto de Java que se usaría para esperar/notificar, se necesitan dos objetos: un mutex y una variable de condición . Estos se inicializaron con pthread_mutex_init y pthread_cond_init.

Donde se habría sincronizado en el objeto Java, use pthread_mutex_lock y pthread_mutex_unlock (tenga en cuenta que en C tiene que emparejarlas usted mismo manualmente). Si no necesita esperar/notificar, simplemente bloquee/desbloquee, entonces no necesita la variable de condición, solo el mutex. Tenga en cuenta que los mutex no son necesariamente "recursivos". Esto significa que si ya está presionando el candado, no podrá volver a tomarlo a menos que configure el indicador de inicio para indicar que desea ese comportamiento.

Donde habría llamado java.lang.Object.wait, llame al pthread_cond_wait o pthread_cond_timedwait.

Donde habría llamado java.lang.Object.notify, llame al pthread_cond_signal.

¿Dónde se habría llamado java.lang.Object.notifyAll, llame pthread_cond_broadcast.

Al igual que en Java, las funciones de espera posibilitan las activaciones espúreas, por lo que necesita alguna condición configurada antes de la llamada a la señal y marcada después de esperar, y debe llamar al pthread_cond_wait en un bucle. Al igual que en Java, el mutex se lanza mientras espera.

diferencia de Java, donde no se puede llamar notify a menos que mantenga el monitor, puede realidad llamar pthread_cond_signal sin sostener el mutex. Sin embargo, normalmente no gana nada, y suele ser una mala idea (porque normalmente quiere bloquear - establecer la condición - señalizar - desbloquear). Por lo tanto, es mejor ignorarlo y tratarlo como Java.

En realidad no hay mucho más que eso, el patrón básico es el mismo que el de Java, y no por casualidad. Sin embargo, lea la documentación para todas esas funciones, ya que hay varios indicadores y comportamientos divertidos que desea conocer y/o evitar.

En C++ se puede hacer un poco mejor que sólo el uso de la API de pthreads. Al menos debes aplicar RAII al bloqueo/desbloqueo de mutex, pero dependiendo de las bibliotecas de C++ que puedas usar, es mejor que utilices un envoltorio más C++ - ish para las funciones pthreads.

4

Usando Condition Variables es una manera de hacerlo: los que están disponibles cuando se utiliza la biblioteca pthread bajo Linux (ver enlace).

Una variable de condición es una variable de tipo pthread_cond_t y se usa con las funciones apropiadas para esperar y más tarde, la continuación del proceso.

1

Si está disponible, puede usar los semáforos POSIX. La biblioteca pthread tiene mutexes, que también podrían funcionar para usted. Google se ...

6

pthread_cond_wait y pthread_cond_signal se puede utilizar para sincronizar la base de una condición

2

Si no le importa la portabilidad, Linux ofrece eventfd, que le proporciona exactamente lo que desea. Cada eventfd mantiene un contador interno. En el modo predeterminado, leyendo desde los bloques eventfd si el contador es cero, de lo contrario regresa inmediatamente. Escribir en él se agregará al contador interno.

La llamada de espera sería simplemente uint64_t buf_a; read(event_fd, &buf_a, sizeof(buf_a));, donde buf debe ser un búfer de 8 bytes. Para notificar el hilo de espera, debe hacer uint64_t buf_b = 1; write(event_fd, &buf_b, sizeof(buf_b));.

6

En su título, combina C y C++ juntos tan casualmente en "C/C++". Espero que no estés escribiendo un programa que sea una mezcla de los dos.

Si está utilizando C++ 11, encontrará una alternativa portátil y (por C++, por lo tanto) mucho más segura/más fácil de usar que pthreads (en sistemas POSIX, por lo general, utiliza pthreads bajo el capó) .

Puede usar std::condition_variable + std::mutex para wait/notify. This example muestra cómo:

#include <iostream> 
#include <string> 
#include <thread> 
#include <mutex> 
#include <condition_variable> 

std::mutex m; 
std::condition_variable cv; 
std::string data; 
bool mainReady = false; 
bool workerReader = false; 

void worker_thread() 
{ 
    // Wait until main() sends data 
    { 
     std::unique_lock<std::mutex> lk(m); 
     cv.wait(lk, []{return mainReady;}); 
    } 

    std::cout << "Worker thread is processing data: " << data << std::endl; 
    data += " after processing"; 

    // Send data back to main() 
    { 
     std::lock_guard<std::mutex> lk(m); 
     workerReady = true; 
     std::cout << "Worker thread signals data processing completed\n"; 
    } 
    cv.notify_one(); 
} 

int main() 
{ 
    std::thread worker(worker_thread); 

    data = "Example data"; 
    // send data to the worker thread 
    { 
     std::lock_guard<std::mutex> lk(m); 
     mainReady = true; 
     std::cout << "main() signals data ready for processing\n"; 
    } 
    cv.notify_one(); 

    // wait for the worker 
    { 
     std::unique_lock<std::mutex> lk(m); 
     cv.wait(lk, []{return workerReady;}); 
    } 
    std::cout << "Back in main(), data = " << data << '\n'; 


    // wait until worker dies finishes execution 
    worker.join(); 
} 

Este código también destaca algunos otros puntos fuertes que C++ tiene sobre C:

  1. este código no contiene un único puntero en bruto (which are treacherous)
  2. lambda expressions
  3. todo tipos de otros syntactic swagg.
Cuestiones relacionadas