Does int sum = func(1) + func(2) cause undefined behavior if func() modifies a global variable
03:40 01 Nov 2023

Inspired by this SO post, I am wondering whether the below snippet causes UB as both add_func() and mul_func() could modify counter concurrently and in an unspecified order:

int counter = 0;

int mul_func(int x) {
  counter *= x;
  x = counter;
  return x;
}

int add_func(int x) {
  counter += x;
  x = counter;
  return x;
}

int main(void) {
  int sum = add_func(3) + mul_func(2);
}

If so, does it help if I add mutex to them?:

int counter = 0;

pthread_mutex_d mtx;

int mul_func(int x) {
  pthread_mutex_lock(&mtx);
  counter *= x;
  x = counter;
  pthread_mutex_unlock(&mtx);
  return x;
}

int add_func(int x) {
  pthread_mutex_lock(&mtx);
  counter += x;
  x = counter;
  pthread_mutex_unlock(&mtx);
  return x;
}

int main(void) {
  pthread_mutex_init(&mtx);
  int sum = add_func(3) + mul_func(2);
  pthread_mutex_destroy(&mtx);
}

While the result can be non-deterministic (as the case of many multi-threading procedures), does the "unsequenced" nature still cause UB even if there is no data race?

c undefined-behavior sequence-points