Today, I tested a multi-thread program on one CPU. The testbed is a FreeBSD
virtual machine, and from lscpu command, it has indeed one CPU:
$ lscpu
Architecture: aarch64
Byte Order: Little Endian
Total CPU(s): 1
Model name: Apple Unknown CPU r0p0 (midr: 610f0000)
The multi-thread program is simple too, just 4
threads add one global variable, and the correct result should be 400000
in every run. If the result is not 400000
, exit the program:
#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#define THREAD_NUM 4
#define SUM_LOOP_SIZE 100000
uint64_t sum;
void *
thread(void *arg)
{
for (int i = 0; i < SUM_LOOP_SIZE; i++) {
sum++;
}
return NULL;
}
int
main()
{
pthread_t tid[THREAD_NUM];
uint64_t counter = 0;
while (1) {
counter++;
for (int i = 0; i < THREAD_NUM; i++) {
int ret = pthread_create(&tid[i], NULL, thread, NULL);
if (ret != 0) {
fprintf(stderr, "Create thread error: %s", strerror(ret));
return 1;
}
}
for (int i = 0; i < THREAD_NUM; i++) {
int ret = pthread_join(tid[i], NULL);
if (ret != 0) {
fprintf(stderr, "Join thread error: %s", strerror(ret));
return 1;
}
}
if (sum != THREAD_NUM * SUM_LOOP_SIZE) {
fprintf(stderr, "Exit after running %" PRIu64 " times, sum=%" PRIu64 "\n", counter, sum);
return 1;
}
sum = 0;
}
return 0;
}
Built and run the program:
$ ./multi_thread_one_cpu
Exit after running 17273076 times, sum=200000
$ ./multi_thread_one_cpu
Exit after running 1539708 times, sum=100000
Change “uint64_t sum;
” to “volatile uint64_t sum;
“, compile and run again:
$ ./multi_thread_one_cpu
Exit after running 20 times, sum=200000
$ ./multi_thread_one_cpu
Exit after running 50 times, sum=200000
Exit much faster.
In summary, when there are multiple threads access same variable, always use lock. P.S., the code can be found here.