Condição de corrida
Ao invés de fazer artigos longos, vou seguir as sugestões e postar pequenos trechos de código isolados (quem sabe um dia vira artigo). Hoje eu estava aqui pensando sobre programação paralela e fui brincar com o .NET. Segue um exemplo de condição de corrida.
Se eu executo um loop 100.000 vezes por 10 threads diferentes, cada uma incrementando um contador global em um, o que esperamos ao fim da execução é ver o valor de 1 milhão, certo? Só se você implementou corretamente sua aplicação multithreaded, com os devidos mecanismos de sincronização. Execute e compare os resultados.
Em anexo está o projeto (VS2008) para vocês brincarem e não vejo porque não compilar até no framework 1.1. Fazia um tempão que não brincava com threads, então em uma programação rápida, deve ter alguma coisa que melhorar.
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;
namespace Threading
{
public class RaceCondition
{
int contadorGeral;
object ElementoSync = new object();
public void ComecaCorrida(Boolean SemControle)
{
contadorGeral = 0;
Thread[] ts = new Thread[10];
for (int i = 0; i < 10; i++)
{
// Cria threads e define qual método o delegate vai chamar, além de dar nome aos bois
ts[i] = new Thread(SemControle ? new ThreadStart(SemControleIncremento) : new ThreadStart(ComControleIncremento));
ts[i].Name = "Thread " + i.ToString();
Console.WriteLine(DumpThread(ts[i]));
}
foreach (Thread t in ts) t.Start();
foreach (Thread t in ts) t.Join();
}
private string DumpThread(Thread t)
{
return "ID Thread: " + t.ManagedThreadId.ToString() + " - " + t.Name;
}
private void SemControleIncremento()
{
int valorlocal = 0;
Random rnd = new Random();
for (int i = 0; i < 100000; i++)
{
valorlocal = contadorGeral;
// Estou usando o spinwait para não causar causar o bloqueio/escalonamento das threads o tempo todo (comportamento do Thread.sleep),
// então mantenho a thread rodando por x ciclos de CPU. O valor 500 é suficiente para não dar tempo da execução do loop
// acabar dentro do quantum alocado para a thread corrente.
Thread.SpinWait(rnd.Next(500));
//Thread.SpinWait(rnd.Next(50));
//Thread.Sleep(rnd.Next(5));
contadorGeral = valorlocal + 1;
}
Console.WriteLine(DumpThread(Thread.CurrentThread) + " " + contadorGeral.ToString());
}
private void ComControleIncremento()
{
int valorlocal = 0;
Random rnd = new Random();
// Sincroniza o acesso a esta região de código para evitar condição de corrida.
lock (ElementoSync)
{
for (int i = 0; i < 100000; i++)
{
valorlocal = contadorGeral;
Thread.SpinWait(rnd.Next(500));
//Thread.SpinWait(rnd.Next(50));
//Thread.Sleep(rnd.Next(5));
contadorGeral = valorlocal + 1;
}
}
Console.WriteLine(DumpThread(Thread.CurrentThread) + " " + contadorGeral.ToString());
}
}
}
static void Main(string[] args)
{
new RaceCondition().ComecaCorrida(true);
Console.WriteLine();
new RaceCondition().ComecaCorrida(false);
Console.ReadLine();
}
[]s
Luciano Caixeta Moreira
=============================================================
This posting is provided "AS IS" with no warranties, and confers no rights
=============================================================
Comments
Anonymous
April 20, 2008
PingBack from http://www.basketballs-sports.info/basketball-chat/?p=136Anonymous
September 27, 2010
Caro Luciano !! bom vi aqui seu algoritmo achei maneiro !! cara estou cursando aqui em Belo Horizonte na Faculdade Uni BH , o Curso de Tecnologia da Informaçao. hoje particpei da aula de S.O , Sistemas Operacionais ,vim antenado para estudar em casa .heheheh bom acho que vc me ajudou um pouco....... Condiçao de corrida ,, Semafaros enfim to na area aqui um futuro GTI no mercado desde ja agradeço e parabéns Leo Bala BH MG (curso GTI UNI BH ) flws