Prosty test:
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define N 100000
volatile int sum = 0;
void *
thr_add(void *_unused)
{
int i;
for (i = 0; i < N; i++)
sum += 1;
return (NULL);
}
void *
thr_sub(void *_unused)
{
int i;
for (i = 0; i < N; i++)
sum -= 1;
return (NULL);
}
int
main()
{
int ret;
pthread_t t1, t2;
ret = pthread_create(&t1, NULL, thr_add, NULL);
assert(ret == 0);
ret = pthread_create(&t2, NULL, thr_sub, NULL);
assert(ret == 0);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("%d\n", sum);
return (0);
}
Daje:
▶ ./test
8484
▶ ./test
-3066
▶ ./test
29127
▶ ./test
-24111
▶ ./test
12583
▶ ./test
27027
Poprawna wersja (atomowe operacje) zawsze daje 0:
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define N 100000
volatile int sum = 0;
void *
thr_add(void *_unused)
{
int i;
for (i = 0; i < N; i++)
__sync_fetch_and_add(&sum, 1);
return (NULL);
}
void *
thr_sub(void *_unused)
{
int i;
for (i = 0; i < N; i++)
__sync_fetch_and_sub(&sum, 1);
return (NULL);
}
int
main()
{
int ret;
pthread_t t1, t2;
ret = pthread_create(&t1, NULL, thr_add, NULL);
assert(ret == 0);
ret = pthread_create(&t2, NULL, thr_sub, NULL);
assert(ret == 0);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("%d\n", sum);
return (0);
}