> For the complete documentation index, see [llms.txt](https://eric-lo.gitbook.io/openmp/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://eric-lo.gitbook.io/openmp/24-synchronization.md).

# Synchronization

OpenMP will not check the data dependencies, data conflicts, race conditions, deadlocks, or code sequences for you. You have to deal with those problems by yourself. OpenMP can have some ways to solve it, but you can also give a better solution(e.g. partition the data properly).

Here we have a race condition problem in the OpenMP version:

{% code title="race.c" %}

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

int main() {
    omp_set_num_threads(2);
    int a=0;
    int i;
    #pragma omp parallel for
    for(i=0; i<20000000; i++) {
        a++;
    }
    printf("a = %d\n", a);
    return 0;
}
```

{% endcode %}

Compile it and run it multiple times, you will found that your results will vary each time you run it. This is the effect of race condition.

```
$ gcc -o race race.c -fopenmp
$ ./race
a = 10406097
$ ./race
a = 15896259
$ ./race
a = 10927636
$ ./race
a = 11958374
$ ./race
a = 15680889
```

How to solve it in OpenMP using the build-in solutions?

* critical: Mutual exclusion, Only one thread at a time can enter a critical region.

{% code title="critical.c" %}

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

int main() {
    omp_set_num_threads(2);
    int a=0;
    int i;
    #pragma omp parallel for
    for(i=0; i<20000000; i++) {
        #pragma omp critical
        {
            a++;
        }
    }
    printf("a = %d\n", a);
    return 0;
}
```

{% endcode %}

After compiling and running multiple times, you will fount you can only get one answer "20000000", which is just what we want. *(You will also find that the running time increases compared with the former one, it's normal.)*

```
$ ./critical
a = 20000000
```

* reduction(op:list): A local copy of each list variable is made and initialized depending on the "op". It will do calculation related with "op" after all the thread finish.

{% code title="reduction.c" %}

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

int main() {
    omp_set_num_threads(2);
    int a=0;
    int i;
    #pragma omp parallel for reduction(+:a)
    for(i=0; i<20000000; i++) {
        a++;
    }
    printf("a = %d\n", a);
    return 0;
}
```

{% endcode %}

Try it by yourself! *(You can also pay attention to the running time)* \
\&#xNAN;***Notice** that  the C compilers for OpenMP also support`*, -, &, |, ^, &&, ||`in reduction.*

* lock routines: just like lock like what you did in pThread.

{% code title="lock.c" %}

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

int main() {
    omp_set_num_threads(2);
    int a=0;
    int i;
    omp_lock_t lock;
    omp_init_lock(&lock);
    #pragma omp parallel for
    for(i=0; i<20000000; i++) {
        omp_set_lock(&lock);
        a++;
        omp_unset_lock(&lock);
    }
    printf("a = %d\n", a);
    return 0;
}
```

{% endcode %}

Try it by yourself and compare the time using different methods!

OpenMP also has many other solutions to synchronization problems, such as barrier, master, single, ordered. You can Google them and get more information about them.

These examples are all using`for`, can you solve synchronization problems not using`for`?
