Pregunta

Necesito diseñar un registrador de flujos seguros. Mi registrador debe tener un método de registro () que simplemente pone en cola un texto que estar conectado. También un registrador debe estar libre de bloqueo - de manera que otro hilo puede registrar mensajes sin bloquear el registrador. Necesito diseñar un subproceso de trabajo que debe esperar por algún evento de sincronización y luego registrar todos los mensajes de la cola utilizando el registro de .NET estándar (que no se thread-safe). Así que lo que me interesa es la sincronización de subproceso de trabajo - y la función de registro. A continuación se muestra un croquis de la clase que diseñé. Creo que debe utilizar Monitor.Wait / Pulso aquí o cualquier otro medio de suspender y reanudar el subproceso de trabajo. Me Don;. T desea pasar ciclos de CPU cuando no hay trabajo para registrador

Permítanme decirlo de otra manera - Quiero diseñar un registrador que No bloquee una persona que llama hilos que lo utilizan. Tengo un sistema de alto rendimiento - y eso es un requisito.

class MyLogger
{
  // This is a lockfree queue - threads can directly enqueue and dequeue
  private LockFreeQueue<String> _logQueue;
  // worker thread
  Thread _workerThread;
  bool _IsRunning = true;

 // this function is used by other threads to queue log messages
  public void Log(String text)
{
  _logQueue.Enqueue(text);
}

// this is worker thread function
private void ThreadRoutine()
{
 while(IsRunning)
 {
   // do something here
 }
}    
}
¿Fue útil?

Solución

"-cerradura libre" no significa que los hilos no se bloquean mutuamente. Esto significa que bloquean entre sí a través de mecanismos muy eficientes, pero también muy difíciles. Sólo necesitan para escenarios de muy alto rendimiento e incluso los expertos se equivocan (mucho).

Su mejor consejo:. Olvidar "lock-libre" y sólo tiene que utilizar una cola "thread-safe"

Yo recomendaría el "bloqueo de cola" de esta página .

Y es una cuestión de elección para incluir el ThreadRoutine (el Comprador) en la propia clase.

Para la segunda parte de su pregunta, depende de lo que "algún evento de sincronización" es exactamente. Si va a utilizar una llamada a un método, y luego dejar que iniciar un hilo de un solo disparo. Si quieres esperar en un semáforo que No Monitor de uso y de pulso. Ellos no son confiables aquí. Utilice un AutoResetEvent / ManualResetEvent.
Cómo superficie que eso depende de cómo desea utilizarlo.

Sus ingredientes básicos deben tener este aspecto:

class Logger
{
    private AutoResetEvent _waitEvent = new AutoResetEvent(false);
    private object _locker = new object();
    private bool _isRunning = true;    

    public void Log(string msg)
    {
       lock(_locker) { _queue.Enqueue(msg); }
    }

    public void FlushQueue()
    {
        _waitEvent.Set();
    }

    private void WorkerProc(object state)
    {
        while (_isRunning)
        {
            _waitEvent.WaitOne();
            // process queue, 
            // ***
            while(true)
            {
                string s = null;
                lock(_locker)
                {
                   if (_queue.IsEmpty) 
                      break;
                   s = _queue.Dequeu();
                }
                if (s != null)
                  // process s
            }
        } 
    }
}

Parte de la discusión parece ser lo que hay que hacer cuando el procesamiento de la cola (marcado ***). Puede bloquear la cola y el proceso de todos los artículos, durante el cual se bloqueará la adición de nuevas entradas (más largo), o bloquear y recuperar los registros uno por uno y sólo bloqueo (muy) poco cada vez. Tengo que Adde último escenario.

Un resumen: Usted no quiere una solución de bloqueo-Libre, pero una cuadra-Libre. Bloque-libre no existe, tendrá que conformarse con algo que bloquea lo menos posible. La última iteración de la muestra mys (incompleta) muestran cómo únicamente para bloquear todo el Enqueue y quitar de la cola de llamadas. Creo que va a ser lo suficientemente rápido.

Otros consejos

¿Su generador de perfiles que se muestra que está experimentando una gran sobrecarga mediante una instrucción sencilla lock? Bloqueo de libre programación es muy difícil de lograr, y si realmente lo necesita que sugeriría algo que existe de una fuente confiable.

No es difícil de hacer este bloqueo libre si tiene operaciones atómicas. Tome una lista de enlace simple; sólo tiene la cabeza puntero.

Función de registro:
1. A nivel local preparar el elemento del registro (nodo con la secuencia de registro).
2. Establecer siguiente puntero del nodo local a cabeza .
3. ATÓMICA: Comparar cabeza con el siguiente nodo de locales, si es igual, reemplace cabeza con la dirección del nodo local
. 4. Si la operación ha fallado, repita desde el paso 2, de lo contrario, el artículo está en la "cola".

Trabajador:
1. Copia cabeza a nivel local.
2. ATÓMICA: Comparar cabeza con un solo local, si es igual, reemplace cabeza con NULL
. 3. Si la operación ha fallado, repita desde el paso 1.
4. Si tuvo éxito, procesar los artículos; los cuales son ahora locales y de fuera de la "cola".

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top