Data sharing in OpenMP makes every variable accessed inside a parallel region explicitly either shared (all threads read and write the same location) or private (each thread gets its own copy). The default for variables declared outside the region is shared, which silently causes a race condition if threads write to them. Local variables in a C function are naturally private, but shared variables require careful classification to avoid bugs:
int x = 0; #pragma omp parallel x = omp_get_thread_num(); // all threads write to the same x — race condition
The private, firstprivate, and lastprivate clauses override this per variable.
int x = 42; #pragma omp parallel private(x) { x = omp_get_thread_num(); // each thread's x is independent, starts uninitialised printf("%d\n", x); } // x is still 42 here; private copies do not write back
firstprivate(x) is like private but initialises each thread's copy to the value x held before the region. lastprivate(x) writes back the value from the logically last iteration to the original variable after the region, which is useful when a loop computes something that should persist. A good habit is to add default(none) to any parallel region, which forces every variable to be classified explicitly and turns accidental sharing into a compile error.