Mutex Example
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <unistd.h> //Header file for sleep(). man 3 sleep for details.
#include <pthread.h>
using namespace std;
pthread_mutex_t mutex;
int counter = 0;
void *thread_handler(void *vargp)
{
pthread_mutex_lock(&mutex);
counter++;
cout << "Job" << *(int *)vargp << " started, counter=" << counter << endl;
/* Run below program with/without sleep(1),
* when sleep is included, we need to have mutex
*/
sleep(1);
cout << "Job" << *(int *)vargp << " finished, counter=" << counter << endl;
pthread_mutex_unlock(&mutex);
return NULL;
}
int main()
{
pthread_t thread_id[30];
int thread_arg[30];
/* Non recursive mutex */
if(pthread_mutex_init(&mutex, NULL)) {
cout << "mutex not initialized successfully" << endl;
}
printf("Before Thread\r\n");
for(int i = 0; i < 5; i++) {
thread_arg[i] = i;
pthread_create(&thread_id[i], NULL, thread_handler, (void *)&thread_arg[i]);
}
for(int i = 0; i < 5; i++) {
pthread_join(thread_id[i], NULL);
}
pthread_mutex_destroy(&mutex);
return 0;
}
Implement Your own Mutex using Spinlock
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <unistd.h> //Header file for sleep(). man 3 sleep for details.
#include <pthread.h>
using namespace std;
#define THREAD_CNT 30
typedef struct {
bool mutex; /* true means available, false means not available */
int lock_cnt;
}MUTEX;
MUTEX m;
int counter = 0;
int mutex_init(MUTEX *p) {
p ->mutex= true;
p ->lock_cnt= 0; /*lock count is not implemented here */
return 0;
}
/* In computer science, read–modify–write is a class of atomic operations
* (such as test-and-set, fetch-and-add, and compare-and-swap)
* that both read a memory location and write a new value into it simultaneously,
* either with a completely new value or some function of the previous value.
* These operations prevent race conditions in multi-threaded applications.
* Typically they are used to implement mutexes or semaphores.
* These atomic operations are also heavily used in non-blocking synchronization.
*/
bool TestAndSet(bool *target)
{
bool temp = *target;
*target = false;
return temp;
}
int mutex_lock(MUTEX *p) {
while(TestAndSet(&p->mutex) == false);
return 0;
}
int mutex_unlock(MUTEX *p) {
p ->mutex= true;
return 0;
}
void *thread_handler(void *vargp)
{
mutex_lock(&m);
counter++;
cout << "Job" << *(int *)vargp << " started, counter=" << counter << endl;
sleep(1);
cout << "Job" << *(int *)vargp << " finished, counter=" << counter << endl;
mutex_unlock(&m);
return NULL;
}
int main()
{
pthread_t thread_id[THREAD_CNT];
int thread_arg[THREAD_CNT];
/* Non recursive mutex */
if(mutex_init(&m)) {
cout << "mutex not initialized successfully" << endl;
}
printf("Before Thread\r\n");
for(int i = 0; i < THREAD_CNT; i++) {
thread_arg[i] = i;
pthread_create(&thread_id[i], NULL, thread_handler, (void *)&thread_arg[i]);
}
for(int i = 0; i < THREAD_CNT; i++) {
pthread_join(thread_id[i], NULL);
}
return 0;
}