Computación paralela en .NET Framework 4.0: La clase Barrier!

Como sabéis, una de las grandes novedades que tendremos en la nueva versión de .NET Framework (4.0) que vendrá de la mano con Visual Studio 2010 es la denominada computación paralela. Muchos son los nuevos elementos que facilitarán el que podamos aprovechar mejor en  nuestras aplicaciones el disponer de un hardware cada vez más potente en lo que a capacidad de procesamiento se refiere (varios núcleos): PLINQ (o LINQ Paralelo), TPL (Parallel Task Library), nuevas primitivas de sincronización, el unified cancellation model y otros que elementos que forman parte de la primera generación de computación paralela en plataforma Microsoft. La idea de este post y de los siguientes es introduciros algunas de estas novedades. En concreto, voy a presentaros una de las nuevas primitivas de sincronización de Threads que vienen con .NET Framework 4.0 de serie: la clase Barrier.

¿Que es la clase Barrier?

Es una primitiva de sincronización que fuerza el paro de una ejecución entre hilos o procesos en un cierto punto y previene futuras ejecuciones hasta que todos los hilos o procesos han llegado al mismo punto. Por lo tanto, Barrier habilita un mecanismo de sincronización de un grupo de Threads que están haciendo un cierto procesamiento a un punto central de sincronización. Dicho punto nos permite esperar a que todos los Threads acaben su trabajo para a continuación sincronizarlas. El mejor simil de la vida real para explicar la clase Barrier es el siguiente:

Supongamos que tres amigos hemos decidido ir de cena, pero que cada uno salimos de una ubicación diferente en un instante diferente de tiempo. La idea es que los tres quedemos en un punto intermedio para tomarnos unas cañas y luego ir juntos al restaurante. Pues bien, cada uno de los amigos es un Thread que se desplaza hacia el punto intermedio (que es nuestra clase Barrier) de alguna forma (este es el trabajo a realizar) para encontrarse con el resto. A partir de este punto intermedio, los tres iremos juntos al restaurante (sincronizados).

image

¿Y cómo se pica esto en Visual Studio?

Pues el ejemplo anterior se traduciría al siguiente código (se trata de un proyecto de aplicación de consola):

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text; 

using System.Threading;  

namespace Barrier_Demo

{

    class Program

    {

        static Barrier sync; 

        static void Main(string[] args)

        { 

            sync = new Barrier(participantCount: 3); 

            var Jc= new Thread(()=>

                IrDeCena("Jc",TimeSpan.FromSeconds(1))); 

            Jc.Start(); 

            var Angel = new Thread(() =>

                IrDeCena("Angel", TimeSpan.FromSeconds(2)));           

            Angel.Start();

 

            var Isa = new Thread(() =>

                IrDeCena("Isa", TimeSpan.FromSeconds(3))); 

            Isa.Start(); 

            Jc.Join();

            Angel.Join();

            Isa.Join(); 

            Console.ReadKey(); 

        }  

        static void IrDeCena(string sNombre, TimeSpan tsHoraEncuentro)

        {

            //Trayecto al punto de encuentro

            Console.WriteLine("[{0}] Saliendo de casa", sNombre);

            Thread.Sleep(tsHoraEncuentro);

            Console.WriteLine("[{0}] Llegada al punto de encuentro", sNombre); 

            //Punto de sincronización

            sync.SignalAndWait();

            Console.WriteLine("[{0}] Saliendo hacia el restaurante", sNombre);          

        }

    }

}

Cómo podéis ver en el código anterior, la clave pasa por definir en primer lugar un tipo Barrier que está definido dentro de System.Threading. A continuación para usar esta nueva clase:

  • Creamos en primer lugar un método IrDeCena que nos permite modelar el trabajo que va a hacer cada Thread (cada amigo) para llegar al punto de encuentro. Básicamente, lo que hacemos es indicar que el participante sale de casa y que tras un cierto tiempo transcurrido (y que definimos con Thread.Sleep()) llega al punto de encuentro. A partir de aquí, cada participante tiene que esperar en este punto de encuentro a que lleguen los demás mediante Sync.SignalAndWait(). Una vez que han llegado todos los participantes, nos vamos al restaurante.
  • En el método Main() es dónde instanciamos el tipo Barrier especificando que el número de participantes es 3. Fijaros en que aquí estamos indicando el nombre del parámetro (participantCount), es decir, estamos haciendo uso de una de las novedades de C# 4.0: Los Named Parameters.
  • Una vez que tenemos el Barrier, vamos creando los distintos Threads (tantos como amigos que se van de cena) especificando el trabajo que van a realizar (IrDeCena). Iniciamos cada Thread llamando a Start() y a continuación hacemos un Join() por cada Thread para permitir que espere a que el resto acaben.

La salida por pantalla que se obtiene nos muestra como los distintos Threads van llegando al punto de encuentro y a partir de este se van de forma sincronizada (os pongo al lado el resultado en el caso de no haber utilizado Barrier):

image image

Sin más, hasta aquí llega este primer post sobre computación paralela en Visual Studio 2010 y .NET Framework 4.0. Espero que os haya resultado interesante.

Publicado por

Juan Carlos González

Juan Carlos es Ingeniero de Telecomunicaciones por la Universidad de Valladolid y Diplomado en Ciencias Empresariales por la Universidad Oberta de Catalunya (UOC). Cuenta con más de 12 años de experiencia en tecnologías y plataformas de Microsoft diversas (SQL Server, Visual Studio, .NET Framework, etc.), aunque su trabajo diario gira en torno a SharePoint & Office 365. Juan Carlos es MVP de Office Servers & Services desde 2015 (anteriormente fue reconocido por Microsoft como MVP de Office 365 y MVP de SharePoint Server desde 2008 hasta 2015), coordinador del grupo de usuarios .NET de Cantabria (Nuberos.Net, www.nuberos.es), co-fundador y coordinador del Grupo de Usuarios de SharePoint de España (SUGES, www.suges.es), así como co-director de la revista gratuita en castellano sobre SharePoint CompartiMOSS (www.compartimoss.com). Hasta la fecha, ha publicado 8 libros sobre SharePoint & Office 365 y varios artículos en castellano y en inglés sobre ambas plataformas.

4 comentarios en “Computación paralela en .NET Framework 4.0: La clase Barrier!”

  1. JC, Barrier en .NET también tiene otros sentidos, de hecho alguno que ya está introducido en .NET y tiene que ver con hacer fences de memoria y evitar reordenaciones del procesador…

    Thread.MemoryBarrier, de memoria, para mas info!

  2. Muy buen post, esto de la computación paralela siempre me ha traide de cabeza desde mis inicios en Java, con proyectos simples se puede llevar bien, pero cuando te metes en cosas grandes… a mi por lo menos me cuesta mucho.

    Será que tengo pocos threads trabajando en mi cerebro??? 🙂

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *