logo
Contato | Sobre...        
rebarba rebarba

Rodrigo Strauss :: Blog


Win32: sincronização parte 2

Preparando esse post eu percebi que o post de sincronização parte 1 não explica nada sobre sincronização, só apresenta o problema que a sincronização resolve. Estou parecendo aqueles vendedores de empresas de software que gastam mais tempo tentando provar que você tem um problema do que realmente mostrando a solução. Agora chegou a hora de mostrar a solução. :-)

Como vimos na primeira parte, o maior problema em programação multithread é o compartilhamento de dados entre as threads. Existem duas solução para isso. A primeira e mais usada é sincronizar o acesso aos dados, de forma que somente uma thread por vez manipule os dados em questão. Ou seja, a solução envolve "eliminar" (notou as aspas?) o multithread da parte que ele atrapalha. A segunda e pouco usada opção é eliminar o compartilhamento dos dados, usando filas, controle restrito de ownership e trabalhando com cópias do dados. Esse é o enfoque usado pelo Erlang, uma nova linguagem de programação.

A forma mais básica para sincronização em vários SOs é o critical section. Esse recurso permite definir um trecho de código que é executado por várias threads, mas que precisa ser sincronizado entre elas. Sincronizado == somente uma thread pode executar esse trecho de código por vez.

Revisando a nossa classe de lista ligada, vamos ver quais são os dados da classe:

template<typename T>

class LinkedList
{
  struct NODE
  {
    NODE* previous;
    NODE* next;
    T data;
  };
 
  NODE rootNode_;
  unsigned int count_;

 ...

A princípio parece que precisamos sincronizar o rootNode_ e o count_. Apesar disso estar correto, não é simples assim, não esqueça que todos os nós apontados pelo rootNode_ são dados controlados pela classe, que também precisam ser sincronizados.

Olhando o fonte dessa classe, todos os métodos manipulam ou lêem essas duas variáveis. A forma mais fácil e óbvia seria cercar com um critical section o corpo de todas as funções da classe.

Em Win32, um critical section é definido pelo objeto (surpresa!) CRITICAL_SECTION. Esse objeto deve ser inicializado e terminado, dessa forma:

CRITICAL_SECTION cs;

//
// adivinha?
//
InitializeCriticalSection(&cs);

//
// aqui entramos no critical section. Quando uma thread está "dentro" de
// um critical section, se alguma outra thread tentar entrar ficará
// travada dentro da funcão EnterCriticalSection até que a primeira
// thread chame LeaveCriticalSection. Isso garante que somente uma thread
// executará esse trecho de código em um dado momento.
//
EnterCriticalSection(&cs);

//
// Saímos do critical section. Isso faz com que a próxima thread que estiver
// esperando no ponto do EnterCriticalSection seja liberada. Note que somente
// uma thread é liberada por vez. Caso mais de uma thread esteja esperando, elas
// são liberadas na ordem que chegaram "na portinha" do critical section
//
LeaveCriticalSection(&cs);

//
// análogo ao CloseHandle
//
DeleteCriticalSection(&cs);

Resumindo: o Critical Section cria um "gargalo", onde só passa uma thread de cada vez. Ah, existe uma coisa interessante a ser acrescentada à explicação do post sobre threads: as threads permitem que um processo execute várias linhas de execução ao mesmo tempo, mas essas linhas de execução podem rodar o mesmo código, que está no mesmo lugar na memória. Ou seja, elas compartilham dados e código executável.

No próximo post iremos para o exemplo prático.


Em 30/01/2009 16:17, por Rodrigo Strauss


  
 
 
Comentários
Ramon | em 01/02/2009 | #
Primeiramente eu quero lhe agradecer pelo trabalho que você faz aqui.Ajuda muitas pesoas.Eu sei que a minha pergunta não tem muito a ver com a matéria acima mas lá vai.

Eu vi na matéria sobre flexibilidade que você escreveu, que você citou a linguagem Ocaml.Você tem interesse em aprender essa linguagem?E você tem idéia de quanto tempo é necessário para ficar bom em C++?

Desculpe a pergunta fora de hora.Espero que você possa me ajudar.

Obrigado
Rodrigo Strauss | website | em 01/02/2009 | #
Eu já li um tutorial de OCaml, mas estou estudando computação distribuída no momento e não estou com vontade de estudar outras linguagens agora. Eu ia escrever que não tenho tempo para isso agora, mas falta de tempo é uma desculpa bem furada, para praticamente qualquer coisa. :-)

Sobre o tempo de C++, é bem relativo, depende do seu esforço. Mas com um ano de C++, ou até mesmo, você já consegue fazer bastante coisa.
Ramon | website | em 05/02/2009 | #
Obrigado por responder minha pergunta.Vou me esforçar para aprender.
Robson L. | em 02/04/2009 | #
Seu site é muito bom. Tem bons artigos e muita informação útil para quem está começando (como eu) ou não. Mas, é uma pena estar tão abandonado ultimamente...
Marcelo S. Muzzi | em 17/05/2009 | #
Estou começando- já li alguns livros e domino as partes teóricas até pointers - em C++ e estou vendo que Win32 é muito importante em C++. Tens alguma dica de livro sobre Win32 que esteja a venda no Brasil(em inglês serve) e que não seja muito caro?

Obrigado.
Charles | em 20/05/2009 | #
Vamos fazer uma campanha: volta, Rodrigo!!!
Rodrigo Strauss | website | em 20/05/2009 | #
Marcelo, veja ../../../content.1bit/weblog/faq_win32
Marcelo S. Muzzi | em 29/05/2009 | #
Uhum.

Vou ver estes livros.

Mas acho que antes vou olhar typedef e o resto. Para que eu seja capaz de aprender todos os pontos de Windows.
rebarba rebarba
  ::::