user13851309
user13851309

Reputation: 79

Reduce overhead in mutex

I am learning mutex currently and the following is the test code. It works perfectly fine. It creates another instance after one is done. Yet, it also introduces overhead according to here. How efficient is locking an unlocked mutex? What is the cost of a mutex?. How can I modify my code to improve the efficiency?

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

typedef struct _context_t {
  uint64_t id;
  char *name;
  bool initialized;
} context_t;

context_t *ctx = NULL;

context_t *get_instance() {
  pthread_mutex_lock(&lock);
  if (ctx == NULL) {
    ctx = (context_t *)malloc(sizeof(context_t));
    assert(ctx != NULL);
    ctx->initialized = false;
  }
  pthread_mutex_unlock(&lock);
  return ctx;
}

int id = 0;

void *do_work(void *arg) {
  context_t *ctx = get_instance();
  if (!ctx->initialized) {
    ctx->name = (char *)arg;
    ctx->id = ++id;
    ctx->initialized = true;
  }
  printf("name=%s\tid=%ld\n", ctx->name, ctx->id);
  return NULL;
}

int main() {
  int rc;
  pthread_t p1, p2;

  rc = pthread_create(&p1, NULL, do_work, "A");
  assert(rc == 0);
  rc = pthread_create(&p2, NULL, do_work, "B");
  assert(rc == 0);

  rc = pthread_join(p1, NULL);
  assert(rc == 0);
  rc = pthread_join(p2, NULL);
  assert(rc == 0);

  if (ctx) {
    free(ctx);
  }
  return 0;
}

Upvotes: 0

Views: 218

Answers (1)

John Zwinck
John Zwinck

Reputation: 249642

Instead of having two threads racing to create the context_t, you should create it once before the threads start, and pass its address to the threads explicitly. Note that you can pass multiple arguments via pthread_create() by putting them in a struct and passing its address.

Then you won't need a mutex at all, because the threads will only read from ctx rather than potentially writing to it.

Upvotes: 2

Related Questions