2009-05-23 6 views
5

¿Podría alguien explicarme la sincronización de la condición?¿Qué es la sincronización de condición?

Un ejemplo (preferiblemente en C#) sería muy apreciado también.

+1

He oído hablar de "sincronización": por lo general, una frase relacionada con varios subprocesos, específicamente con varios tipos de "bloqueo" que pueden ser necesarios para 'sincronizar' los hilos con el fin de hacer que el código sea "seguro para subprocesos" ". Pero no sé, específicamente, "* condición * sincronización". – ChrisW

Respuesta

8

Parece que su profesor está hablando de rosca. Threading permite a los programas de computadora hacer más de una cosa a la vez. El hecho de iniciar un nuevo hilo mientras uno ya está ejecutándose se llama "hacer girar un hilo" por los programadores de computadoras.

Los subprocesos pueden compartir el mismo espacio de memoria. Sincronización de condición (o simplemente sincronización) es cualquier mecanismo que protege áreas de memoria para que no sean modificadas por dos subprocesos diferentes al mismo tiempo.

Digamos que está haciendo compras y que la esposa está en casa pagando las facturas. Este es un ejemplo ingenuo, y realmente no funciona de esta manera en la vida real, pero servirá como una simple ilustración.

Su esposa está pagando una factura en línea. Al mismo tiempo, está deslizando su tarjeta de crédito en la tienda de comestibles. Ambos actos implican sacar dinero de su cuenta de cheques. Para simular esta actividad, escribimos el siguiente código:

public class MyBanking 
{ 
    static double myAccountBalance; 
    // 
    public void DebitAccount(double debitAmount) 
    { 
     Console.Writeline("Your Old Balance is: " + myAccountBalance.ToString()); 
     Console.Writeline("Your Debit is:  " + debitAmount.ToString()); 
     myAccountBalance = myAccountBalance - amount; 
     Console.Writeline("Your New Balance is: " + myAccountBalance.ToString()); 
    } 
} 

Hipotéticamente, su esposa se está ejecutando una instancia ("copia") de esta clase en un hilo, se está ejecutando una instancia en otro hilo. La variable myAccountBalance se declara estática para permitir que se comparta entre ambas instancias en ejecución (usted y su esposa solo tienen una cuenta de cheques).

Usted hace su débito llamando al código como este:

MyBanking bankingObject = new MyBanking(); 
bankingObject.DebitAccount(100); 

Su esposa hace que su débito al mismo tiempo:

MyBanking bankingObject = new MyBanking(); 
bankingObject.DebitAccount(50); 

¿Qué pasa si el hilo se ve interrumpido por el hilo de su esposa después de imprimir su saldo anterior en la pantalla, pero antes de que se imprima el nuevo saldo? El hilo de su esposa carga la cuenta y devuelve el control a su hilo.Su esposa ve esto en la pantalla:

Your Old Balance is: 2000 
Your Debit is:  50 
Your New Balance Is: 1950 

Cuando el equipo imprime el nuevo equilibrio en la pantalla, será mal, porque de débito de su esposa se han contabilizado también. Verá algo como esto:

Your Old Balance is: 2000 
Your Debit is:  100 
Your New Balance Is: 1850 

Para corregir esto, rodeamos nuestro código de método con una instrucción de bloqueo. La instrucción de bloqueo hace que todos los demás hilos esperen a que termine nuestra instancia. El nuevo código es el siguiente: Hilo de

public class MyBanking 
{ 
    static double myAccountBalance; 
    // 
    public void DebitAccount(double debitAmount) 
    { 
     lock (this) 
     { 
      Console.Writeline("Your Old Balance is: " + myAccountBalance.ToString()); 
      Console.Writeline("Your Debit is:  " + debitAmount.ToString()); 
      myAccountBalance = myAccountBalance - amount; 
      Console.Writeline("Your New Balance is: " + myAccountBalance.ToString()); 
     } 
    } 
} 

Su esposa ahora esperará a que su código dentro de la instrucción de bloqueo para terminar la ejecución, antes de que el código de su esposa comienza a ejecutar. Su nuevo saldo ahora será correcto, porque ya no existe la posibilidad de que el hilo de su esposa cambie el saldo mientras completa SU transacción. En la pantalla, ahora ve esto:

Your Old Balance is: 2000 
Your Debit is:  100 
Your New Balance Is: 1900 

Su esposa verá esto:

Your Old Balance is: 1900 
Your Debit is:  50 
Your New Balance Is: 1850 

Esta es la sincronización.

+0

También hay algo llamado una variable condicional. Vea este artículo para más detalles: http://en.wikipedia.org/wiki/Monitor_%28synchronization%29 –

+0

La esposa tiene un resultado incorrecto. 1900 - 50! = 1800 –

+0

@IgorGorjanc: Gracias. –

2

Básicamente se trata de un patrón de diseño para las discusiones que necesitan

a) sincronizar el acceso a un recurso

b) a veces esperar a que otros hilos hasta cierta condiciones se cumple

le preguntas a esto de una El contexto de C#, .NET brinda soporte para esto con Monitor.Wait y Monitor.Pulse (y con envoltorios alrededor de varios objetos Win32 como WaitEventhandle).

Aquí hay un buen queue example en SO.

Los principales detalles técnicos se ven como:

lock(buffer) // is Monitor.Enter(buffer) ... finally Monitor.Leave(buffer) 
{ 
    while (buffer.Count < 1) 
    { 
     Monitor.Wait(buffer); 
    } 
    ... 
} 

Nótese cómo hay una espera mientras está bloqueado allí. Parece un punto muerto, pero Wait liberará el bloqueo mientras espera. El código dentro del lock() { } todavía tiene acceso exclusivo al búfer cuando se ejecuta.

Y luego otro hilo tiene que indicar cuando se pone algo en la memoria intermedia:

Monitor.Pulse(buffer); 
1

El código anterior es casi correcto, pero en realidad es incorrecto. Al usar lock(this), solo bloqueará su instancia de la clase MyBanking, pero su esposa bloqueará la suya. Para bloquear el acceso a la variable compartida puede o bien bloquear el tipo (es decir lock(typeof(MyBanking))) o se puede introducir una nueva variable compartida y bloquear que (no se puede bloquear un int por lo general las personas crear un objeto de la siguiente manera.

class MyBanking 
{ 
    static object lockObj = new object(); 
    static double myAccountBalance; 
    public void DebitAccount(double debitAmount) 
    { 
     lock (lockObj) 
1

sincronización ha sido claramente explicado ya. Sin embargo, condición de sincronización dicta específicamente que un proceso/hilo ejecuta solamente después de que se cumpla alguna condición. Típicamente, la condición será que algún otro proceso/hilo ya ha ejecutado.

En el ejemplo dado de cargar una cuenta y ver el saldo. Si la visualización de su saldo era un método sincronizado por separado y queríamos ver el saldo solo después de que su cuenta haya sido cargada, entonces esto requeriría la sincronización de la condición.

La sincronización de la condición está muy bien descrita por el producer-consumer problem.

Cuestiones relacionadas