Welcome to our deep dive into C Mutex using pthread_mutex_t! In this lesson, we'll explore how to manage concurrent access to shared resources in C programs using mutexes.
A Mutex, short for Mutual Exclusion, is a synchronization primitive used in concurrent programming to ensure only one thread can access a shared resource at a time, preventing data race and inconsistency.
In C, the pthread_mutex_t is a built-in synchronization object used to manage mutual exclusion. It's used in conjunction with the POSIX threads library, which provides a platform-independent way to create and manage multiple threads.
Before using a mutex, it must be initialized. Here's an example of creating and initializing a mutex:
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t my_mutex;
int main() {
int ret;
// Initialize mutex with default attributes (recursive mutex)
ret = pthread_mutex_init(&my_mutex, NULL);
if (ret != 0) {
printf("Mutex initialization failed: %s\n", strerror(ret));
return 1;
}
// Your code here...
// Destroy mutex when done
ret = pthread_mutex_destroy(&my_mutex);
if (ret != 0) {
printf("Mutex destruction failed: %s\n", strerror(ret));
}
return 0;
}š” Pro Tip: Initializing a mutex with non-default attributes is also possible using the pthread_mutexattr_t attribute object.
To lock a mutex, use the pthread_mutex_lock() function:
ret = pthread_mutex_lock(&my_mutex);
if (ret != 0 && ret != EDEADLK) {
printf("Mutex locking failed: %s\n", strerror(ret));
return 1;
}Locking a mutex blocks the calling thread until the mutex is available. If the mutex is already locked by another thread, the calling thread will be blocked until the mutex is unlocked.
To unlock a mutex, use the pthread_mutex_unlock() function:
ret = pthread_mutex_unlock(&my_mutex);
if (ret != 0) {
printf("Mutex unlocking failed: %s\n", strerror(ret));
}š” Pro Tip: If a thread attempts to lock a mutex it already holds, the function call will return immediately with no error.
Now that you have a good understanding of creating and locking/unlocking mutexes, let's create a practical example. Suppose we have a shared variable counter that needs to be incremented by multiple threads concurrently:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t my_mutex;
int counter = 0;
void* increment_counter(void* arg) {
int i;
for (i = 0; i < 100000; i++) {
pthread_mutex_lock(&my_mutex);
counter++;
pthread_mutex_unlock(&my_mutex);
}
return NULL;
}
int main() {
int ret, num_threads = 4;
pthread_t threads[num_threads];
// Initialize mutex with default attributes
ret = pthread_mutex_init(&my_mutex, NULL);
if (ret != 0) {
printf("Mutex initialization failed: %s\n", strerror(ret));
return 1;
}
// Create and start threads
int i;
for (i = 0; i < num_threads; i++) {
ret = pthread_create(&threads[i], NULL, increment_counter, NULL);
if (ret != 0) {
printf("Thread creation failed: %s\n", strerror(ret));
return 1;
}
}
// Wait for threads to finish
for (i = 0; i < num_threads; i++) {
ret = pthread_join(threads[i], NULL);
if (ret != 0) {
printf("Thread joining failed: %s\n", strerror(ret));
}
}
// Destroy mutex when done
ret = pthread_mutex_destroy(&my_mutex);
if (ret != 0) {
printf("Mutex destruction failed: %s\n", strerror(ret));
}
printf("Counter value: %d\n", counter);
return 0;
}In this example, we create four threads that increment the shared variable counter while using a mutex to prevent data race. Running the code and observing the output shows that the counter value is consistent, as the mutex ensures only one thread accesses the counter at a time.
What does the `pthread_mutex_lock()` function do in C programming?
That's it for this lesson on C Mutex using pthread_mutex_t! By now, you should have a good understanding of how to manage concurrent access to shared resources using mutexes in C. As always, practice makes perfect, so go ahead and experiment with mutexes in your own projects. š
Happy coding!