# Race condition e sincronização de threads com mutex

Para entendermos o problema que a *sincronização com mutex* resolve, vamos primeiro trazer o problema.&#x20;

A ideia é escrever um programa que cria 5 threads, onde cada thread faz um **incremento de 100 mil vezes** em uma variável (counter) compartilhada entre todas as threads.&#x20;

Ao fim do programa, queremos que o *counter* tenha um valor total de 500.000, ou seja, 5 threads x 100.000. Certo? Vamos então à implementação do programa:

```c
#include <stdio.h>
#include <pthread.h>

#define NUM_THREADS 5
#define INCREMENTS 100000

int counter = 0; // Variável compartilhada entre as threads

void* increment(void* arg) {
	for (int i = 0; i < INCREMENTS; i++) {
		counter++; // Incrementa a variável compartilhada
	}
	return NULL;
}

int main() {
	pthread_t threads[NUM_THREADS];

	// Cria as threads
	for (int i = 0; i < NUM_THREADS; i++) {
		pthread_create(&threads[i], NULL, increment, NULL);
	}

	// Aguarda as threads terminarem
	for (int i = 0; i < NUM_THREADS; i++) {
		pthread_join(threads[i], NULL);
	}

	printf("Valor final do counter compartilhado: %d (esperado: %d)\n", counter, NUM_THREADS * INCREMENTS);
	return 0;
}
```

Tudo ok até aqui, pois os comentários no código são auto-explicativos. Vamos executar o programa e:

```
Valor final do counter compartilhado: 282989 (esperado: 500000)
```

*Eita!* Note que o valor final do counter ficou bem abaixo do esperado. Experimente rodar outras vezes e repare que a cada execução, o valor final será diferente.&#x20;

Isto, *senhoras e senhores*, é a maravilha da concorrência. Não temos controle algum sobre a ordem e execução das tarefas!

> Sim, vou repetir isso inúmeras vezes neste guia kk

## Race condition

O que temos aqui é examente um cenário de **race condition**, ou *condição de corrida*, onde o valor final de um recurso compartlihado depende da ordem de execução das threads. Em outras palavras, este recurso precisa ser **sincronizado** entre as threads.&#x20;

E para isto, recorremos ao uso de travas - **locks** - que, para nossa sorte, a biblioteca padrão implementa uma abstração chamada **mutex** (exclusão mútua), através do uso da função `pthread_mutex_lock` .

## Mutex

O uso de mutex em C é muito simples. Tudo o que precisamos é de criar uma variável *compartilhada* que irá representar o mutex:

```c
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
```

E em volta da mutação do recurso, fazemos o bloqueio e desbloqueio do mutex:

```c
pthread_mutex_lock(&mutex);    // Bloqueia o mutex
counter++;                     // Incrementa a variável compartilhada
pthread_mutex_unlock(&mutex);  // Desbloqueia o mutex
```

O que vai acontecer, na prática, é que quando uma thread estiver com o mutex, e caso outra tente acessar o mesmo mutex, o sistema irá colocar esta outra thread em "wait" até que o mutex seja liberado (unlock).

<figure><img src="/files/gC6zp3hIfpHFRsk0Jb1p" alt="" width="563"><figcaption></figcaption></figure>

Agora vamos à implementação completa do código, sincronizado com mutex:

{% code title="race-condition-mutex.c" lineNumbers="true" %}

```c
#include <stdio.h>
#include <pthread.h>

#define NUM_THREADS 5
#define INCREMENTS 100000

int counter = 0; // Variável compartilhada entre as threads
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // Mutex para proteger o acesso

void* increment(void* arg) {
	for (int i = 0; i < INCREMENTS; i++) {
		pthread_mutex_lock(&mutex); // Bloqueia o mutex
		counter++; // Incrementa a variável compartilhada
		pthread_mutex_unlock(&mutex); // Desbloqueia o mutex
	}
	return NULL;
}

int main() {
	pthread_t threads[NUM_THREADS];

	// Cria as threads
	for (int i = 0; i < NUM_THREADS; i++) {
		pthread_create(&threads[i], NULL, increment, NULL);
	}

	// Aguarda as threads terminarem
	for (int i = 0; i < NUM_THREADS; i++) {
		pthread_join(threads[i], NULL);
	}

	printf("Valor final do counter compartilhado: %d (esperado: %d)\n", counter, NUM_THREADS * INCREMENTS);
	return 0;
}
```

{% endcode %}

```
Valor final do counter compartilhado: 500000 (esperado: 500000)
```

**Yay!** *Quantas palmas merece o mutex?*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://concorrencia101.leandronsp.com/parte-ii-concorrencia-em-diferentes-linguagens/concorrencia-em-c/race-condition-e-sincronizacao-de-threads-com-mutex.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
