mutex
mutex word is shot form of mutual exclusion. In computer, mutex is a synchronization methood which prevent multiple threads from accessing the critical section(shared resource/shared block of code/shared memory etc).
lets look at this program.
here we are creating two threads and both threads are trying to write a common file same time without any synchronization.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#define FILE_TO_LOG "log.txt"
void *callback1(void *arg)
{
int fd;
int ret;
fd = open(FILE_TO_LOG, O_WRONLY | O_CREAT, 0666);
if (fd < 0) {
fprintf(stderr, "T1: failed to open %s file\n", FILE_TO_LOG);
pthread_exit(NULL);
}
ret = write(fd, "Hello\n", 6);
if (ret <= 0) {
fprintf(stderr, "T1: failed to write %s file\n", FILE_TO_LOG);
} else {
printf("T1: %d byte written to %s\n", ret, FILE_TO_LOG);
}
close(fd);
pthread_exit(NULL);
}
void *callback2(void *arg)
{
int fd;
int ret;
fd = open(FILE_TO_LOG, O_WRONLY | O_CREAT, 0666);
if (fd < 0) {
fprintf(stderr, "T2: failed to open %s file\n", FILE_TO_LOG);
pthread_exit(NULL);
}
ret = write(fd, "Hi\n", 3);
if (ret <= 0) {
fprintf(stderr, "T2: failed to write %s file\n", FILE_TO_LOG);
} else {
printf("T2: %d byte written to %s\n", ret, FILE_TO_LOG);
}
close(fd);
pthread_exit(NULL);
}
int main()
{
int ret;
pthread_t tid1, tid2;
unlink(FILE_TO_LOG);
/* creating first thread */
ret = pthread_create(&tid1, NULL, callback1, NULL);
if (ret != 0) {
fprintf(stderr, "failed to create thread 1\n");
return -1;
}
/* creating second thread */
ret = pthread_create(&tid2, NULL, callback2, NULL);
if (ret != 0) {
fprintf(stderr, "failed to create thread 2\n");
pthread_join(tid1, NULL);
return -1;
}
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
Now look at this program having same usecase with mutex synchronization
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#define FILE_TO_LOG "log.txt"
pthread_mutex_t lock;
void *callback1(void *arg)
{
int fd;
int ret;
pthread_mutex_lock(&lock);
fd = open(FILE_TO_LOG, O_WRONLY | O_APPEND | O_CREAT, 0666);
if (fd < 0) {
fprintf(stderr, "T1: failed to open %s file\n", FILE_TO_LOG);
pthread_exit(NULL);
}
ret = write(fd, "Hello\n", 6);
if (ret <= 0) {
fprintf(stderr, "T1: failed to write %s file\n", FILE_TO_LOG);
} else {
printf("T1: %d byte written to %s\n", ret, FILE_TO_LOG);
}
close(fd);
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
}
void *callback2(void *arg)
{
int fd;
int ret;
pthread_mutex_lock(&lock);
fd = open(FILE_TO_LOG, O_WRONLY | O_APPEND | O_CREAT, 0666);
if (fd < 0) {
fprintf(stderr, "T2: failed to open %s file\n", FILE_TO_LOG);
pthread_exit(NULL);
}
ret = write(fd, "Hi\n", 3);
if (ret <= 0) {
fprintf(stderr, "T2: failed to write %s file\n", FILE_TO_LOG);
} else {
printf("T2: %d byte written to %s\n", ret, FILE_TO_LOG);
}
close(fd);
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
}
int main()
{
int ret;
pthread_t tid1, tid2;
unlink(FILE_TO_LOG);
ret = pthread_mutex_init(&lock, NULL);
if (ret != 0) {
fprintf(stderr, "failed to init mutex\n");
return -1;
}
/* creating first thread */
ret = pthread_create(&tid1, NULL, callback1, NULL);
if (ret != 0) {
fprintf(stderr, "failed to create thread 1\n");
return -1;
}
/* creating second thread */
ret = pthread_create(&tid2, NULL, callback2, NULL);
if (ret != 0) {
fprintf(stderr, "failed to create thread 2\n");
pthread_join(tid1, NULL);
return -1;
}
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
Now its working good as pre usecase, wait a min, still there are some critical isue the the above program. lets figure it out.
TODO
Conditional sync variables
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#define FILE_TO_LOG "log.txt"
pthread_mutex_t lock;
pthread_cond_t cond;
void *callback1(void *arg)
{
int fd;
int ret;
pthread_mutex_lock(&lock);
fd = open(FILE_TO_LOG, O_WRONLY | O_APPEND | O_CREAT, 0666);
if (fd < 0) {
fprintf(stderr, "T1: failed to open %s file\n", FILE_TO_LOG);
pthread_exit(NULL);
}
ret = write(fd, "Hello\n", 6);
if (ret <= 0) {
fprintf(stderr, "T1: failed to write %s file\n", FILE_TO_LOG);
} else {
printf("T1: %d byte written to %s\n", ret, FILE_TO_LOG);
}
close(fd);
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);
pthread_exit(NULL);
}
void *callback2(void *arg)
{
int fd;
int ret;
pthread_mutex_lock(&lock);
pthread_cond_wait(&cond, &lock);
fd = open(FILE_TO_LOG, O_WRONLY | O_APPEND | O_CREAT, 0666);
if (fd < 0) {
fprintf(stderr, "T2: failed to open %s file\n", FILE_TO_LOG);
pthread_exit(NULL);
}
ret = write(fd, "Hi\n", 3);
if (ret <= 0) {
fprintf(stderr, "T2: failed to write %s file\n", FILE_TO_LOG);
} else {
printf("T2: %d byte written to %s\n", ret, FILE_TO_LOG);
}
close(fd);
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
}
int main()
{
int ret;
pthread_t tid1, tid2;
unlink(FILE_TO_LOG);
ret = pthread_mutex_init(&lock, NULL);
if (ret != 0) {
fprintf(stderr, "failed to init mutex\n");
return -1;
}
ret = pthread_cond_init(&cond, 0);
if (ret != 0) {
fprintf(stderr, "failed to init condition\n");
return -1;
}
/* creating first thread */
ret = pthread_create(&tid1, NULL, callback1, NULL);
if (ret != 0) {
fprintf(stderr, "failed to create thread 1\n");
return -1;
}
/* creating second thread */
ret = pthread_create(&tid2, NULL, callback2, NULL);
if (ret != 0) {
fprintf(stderr, "failed to create thread 2\n");
pthread_join(tid1, NULL);
return -1;
}
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
lets analyze above program.
©2023-2024 rculock.com