Locks

Locks provide a way for restricting multiple threads from accessing a resource at the same time.

#include <stdio.h>
#include <pthread.h>

int a;
pthread_mutex_t mutex;

void *func(void *arg) {
for (int i = 0; i != 5; ++i) {
pthread_mutex_lock(&mutex);
printf("%d\n", a++);
pthread_mutex_unlock(&mutex);
}
return 0;
}

int main() {
pthread_t thread1, thread2;
pthread_mutex_init(&mutex, 0);
pthread_create(&thread1, 0, &func, 0);
pthread_create(&thread2, 0, &func, 0);
pthread_join(thread1, 0);
pthread_join(thread2, 0);
}

The function func is executed twice in separate threads. These threads access and modify integer a at the same time. Acquiring a lock on a mutex before accessing a thread-shared variable insures that the current thread will execute the proceeding lines of code exclusively before releasing the lock.

A mutex can be implemented by using an atomic data type. A data type is atomic if it is thread-safe and it appears to happen instantaneously to the rest of the system. Using an atomic integer, a very simple mutex can be implemented like this:

#ifndef MUTEX_H
#define MUTEX_H

#include "Atom.h"

class Mutex {
protected:
Atom atom;
public:
Mutex() : atom() {}

void lock() {
while ((atom = 1) == 1);
}
bool trylock() {
return (atom = 1) == 0;
}
void unlock() {
atom = 0;
}

};

#endif

Assuming Atom works on 32-bit integers, the Atom assignment operators will assign the specified value to the underlying integer and then return the previous value stored. The lock function will keep assigning 1 (to lock it) to the Atom until it’s previous value is 0 (from an unlock).

The Atom class is hardware specific, but for x86 processors, it might be implemented like this:

#ifndef ATOM_H
#define ATOM_H

#include <stdint.h>

class Atom {
protected:
volatile int32_t value;
public:
Atom() : value() {}
Atom(int32_t val) : value(val) {}

inline int32_t operator = (int32_t val) {
asm("xchgl %0, %1" : "+r"(val), "+m"(value));
return val;
}
};

#endif

x86 gives exclusive access to the xchg instruction that references a memory location. Here we swap the old value of the atomic integer with a specified new value, returning the old value that was swapped out.

Even though C++ doesn’t have built-in mutex classes, they can be implemented by using C++11’s atomic template classes.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: