How to use pthread_mutex_trylock? - c

Using trylock:
FILE *fp;
pthread_mutex_t demoMutex;
void * printHello (void* threadId)
{
pthread_mutex_trylock (&demoMutex);
pthread_t writeToFile = pthread_self ();
unsigned short iterate;
for (iterate = 0; iterate < 10000; iterate++)
{
fprintf (fp, " %d ", iterate, 4);
fprintf (fp, " %lu ", writeToFile, sizeof (pthread_t));
fprintf (fp, "\n", writeToFile, 1);
}
pthread_mutex_unlock (&demoMutex);
pthread_exit (NULL);
}
and then main ():
int main ()
{
pthread_t arrayOfThreadId [5];
int returnValue;
unsigned int iterate;
fp = fopen ("xyz", "w");
pthread_mutex_init (&demoMutex, NULL);
for (iterate = 0; iterate < 5; iterate++)
{
if (returnValue = pthread_create (&arrayOfThreadId [iterate],
NULL,
printHello,
(void*) &arrayOfThreadId [iterate]) != 0)
{
printf ("\nerror: pthread_create failed with error number %d", returnValue);
}
}
for (iterate = 0; iterate < 5; iterate++)
pthread_join (arrayOfThreadId [iterate], NULL);
return 0;
}
Here the output first prints some of the first thread and then the rest, and then again the first. The lock isn't working. If I replace the same with pthread_mutex_lock every thing gets shown very sequentially!
What's the ridiculous mistake here?

It does not make sense to call pthread_mutex_trylock() without testing the result.
If it fails to acquire the mutex, you should not enter the critical section, and you should not unlock it later. For example, you could rewrite it like so (note that you are also very confused about how fprintf() should be called):
void *printHello(void *threadId)
{
if (pthread_mutex_trylock(&demoMutex) == 0)
{
unsigned short iterate;
for (iterate = 0; iterate < 10000; iterate++)
{
fprintf (fp, " %d\n", iterate);
}
pthread_mutex_unlock (&demoMutex);
}
pthread_exit (NULL);
}
However, it probably makes more sense to use pthread_mutex_lock() instead of pthread_mutex_trylock(), so that your thread will wait for the mutex to be available if it is contended. pthread_mutex_lock() is in almost all cases what you want; the _trylock variant is only for optimising some unusual cases - if you ever encounter a situation where _trylock is needed, you'll know.

...
while (pthread_mutex_trylock(&demoMutex) == 0)
...
Your code makes no sense. Where is it force locked? It's like a not working spinlock that use more CPU?!
trylock returns 0 when it locks, so:
if(!pthread_mutex_trylock(&demoMutex))
{
// mutex locked
}
The pthread_mutex_trylock() function shall return zero if a lock on
the mutex object referenced by mutex is acquired. Otherwise, an error
number is returned to indicate the error.

caf had a great answer on how to use it. I just had to grab that explanation for myself, however I did learn that pthread_mutex_lock() has far more overhead in class and just tested it out using the <time.h> lib and the performance for my loop was significantly increased. Just adding in that two cents since he mentioned that maybe you should use pthread_mutex_lock() instead!
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUM_THREADS 4
#define LOOPS 100000
int counter;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// using pthread_mutex_lock
void* worker() {
for (int i = 0; i < LOOPS; i++) {
pthread_mutex_lock(&mutex);
counter++;
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
// using try_lock - obviously only use one at a time
void* worker() {
for (int i = 0; i < LOOPS; i++) {
while (pthread_mutex_trylock(&mutex) != 0) {
// wait - treated as spin lock in this example
}
counter++;
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
clock_t begin = clock();
pthread_t t[NUM_THREADS];
int rc;
counter = 0;
for (int i = 0; i < NUM_THREADS; i++) {
rc = pthread_create(&t[i], NULL, worker, NULL);
if (rc) {
printf("Thread #%d failed\n", i);
}
}
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(t[i], NULL);
}
printf("%d\n", counter);
clock_t end = clock();
double time = (double)(end - begin) / CLOCKS_PER_SEC;
printf("Time Spent: %f", time);
return 0;
}
Obviously you would comment out one worker to test it, but if you try it out, I get Time Spent: 1.36200 as an average for pthread_mutex_lock() and Time Spent: 0.36714 for pthread_mutex_trylock().
Goes faster again if you use Atomics.

The code is meant to block to ensure mutual exclusion where you call pthread_mutex_trylock(). Otherwise it is undefined behavior. Therfore you must call pthread_mutex_lock().

a modified version of force locked with while loop should be more stable.
void *printHello(void *threadId)
{
while (pthread_mutex_trylock(&demoMutex) == 0)
{
unsigned short iterate;
for (iterate = 0; iterate < 10000; iterate++)
{
fprintf (fp, " %d\n", iterate);
}
pthread_mutex_unlock (&demoMutex);
break;
}
pthread_exit (NULL);
}`

The use of pthread_mutex_trylock is used to ensure that tou will not cause a race to a specific command.
In order to do so, you must use pthread_mutex_trylock as a condition! an not assume that it would work by it self.
example-
while(pthread_mutex_trylock(&my_mutex)==0){
printf("The mutex is in my control!!\n");
}
that way you can be sure that even if the mutex is now locked, you are doing abusy-waiting for it in that particular thread.

Related

i wanna know what's the diffrent between mutex_lock and pthread_join? [duplicate]

This question already has answers here:
Difference between mutex lock and pthread_join
(2 answers)
Closed last year.
What's the difference between mutex_lock and pthread_join in these two source codes? They seem both to do the same thing, making the main function wait for the thread to finish execution.
This code:
#include "philo.h"
typedef struct s_bablo
{
pthread_mutex_t mutex;
} t_bablo;
void *myturn(void *arg)
{
t_bablo *bablo = (t_bablo *)arg;
int i = 0;
while(i < 10)
{
printf("My Turn ! %d\n", i);
i++;
sleep(1);
}
pthread_mutex_unlock(&bablo->mutex);
}
void *yourturn()
{
int i = 0;
while(i < 5)
{
printf("Your Turn ! %d\n", i);
i++;
sleep(1);
}
}
int main ()
{
t_bablo bablo;
pthread_mutex_init(&bablo.mutex, NULL);
pthread_t ph;
pthread_mutex_lock(&bablo.mutex);
pthread_create(&ph, NULL, myturn, &bablo);
yourturn();
pthread_mutex_lock(&bablo.mutex);
}
And this code :
#include "philo.h"
void *myturn(void *arg)
{
int i = 0;
while(i < 10)
{
printf("My Turn ! %d\n", i);
i++;
sleep(1);
}
}
void *yourturn()
{
int i = 0;
while(i < 5)
{
printf("Your Turn ! %d\n", i);
i++;
sleep(1);
}
}
int main ()
{
pthread_t ph;
pthread_create(&ph, NULL, myturn, NULL);
yourturn();
pthread_join(ph, NULL);
}
not to be rude but you can easily find the difference by googling both functions name...
Though pthread_mutex_lock is for variables. It locks this variable for the current running thread. Thus no other thread can use it, they have to wait for pthread_mutex_unlock to use it.
pthread_join waits for the specified thread to finish it's execution before continuing
I encourage you to read the man pages, they are really self explanatory.

Which one is correct about the usage of pthread_mutex_lock() function?

I'm learning how to use global variables through multithreading, but I have a problem now: about pthread_mutex_lock() and pthread_mutex_unlock().
Correct is usage in function1 or function2? If neither, how to use it correctly?
I just modified one of the elements in the array at that time. For example, after thread1 changed AllSensorInfoArray[2][66].sensorType, the thread1 will change AllSensorInfoArray[2][67].sensorType,now thread2 can change AllSensorInfoArray[2][66].sensorType. In other words, multiple threads are not allowed to modify AllSensorInfoArray[2][66].sensorType at the same time.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t AllSensorMutex;
void *function1(void *arg)
{
int t = 0, i = 0;
/*
some codes
*/
pthread_mutex_lock(&AllSensorMutex);
for (t = 0; t < 100; t++)
{
AllSensorInfoArray[i][t].sensorType = allData[2+t];
}
pthread_mutex_unlock(&AllSensorMutex);
/*
some codes
*/
}
void *function2(void *arg)
{
/*
some codes
*/
int t = 0, i = 0;
for (t = 0; t < 100; t++)
{
pthread_mutex_lock(&AllSensorMutex);
AllSensorInfoArray[i][t].sensorType = allData[2+t];
pthread_mutex_unlock(&AllSensorMutex);
}
/*
some codes
*/
}
int main(void)
{
while(pthread_mutex_init(&AllSensorMutex, NULL))
{
printf("(%s) write mutex init error!\n", __FUNCTION__);
sleep(1);
}
pthread_t thread1;
pthread_t thread2;
int ret = pthread_create(&thread1, NULL, function1, NULL);
if (ret != 0)
{
printf("(%s) failed to create a pthread, return error code : %d.\n", __FUNCTION__, ret);
exit(-1);
}
ret = pthread_create(&thread2, NULL, function2, NULL);
if (ret != 0)
{
printf("(%s) failed to create a pthread, return error code : %d.\n", __FUNCTION__, ret);
exit(-1);
}
while (1)
{
sleep(1);
}
}
Correct is usage in function1 or function2?
Both are equally correct, and will work. The first one is "better" for this particular case.
The first one, which takes the mutex for the duration of the loop is more efficient, because there is less overhead (of locking and unlocking the mutex).
It is best suited for things like copying data.
The second one, which takes the mutex for the duration of accessing each element, is better suited when the modification is more complicated and may take some time (relatively speaking), and you only need to access that one element. However, then you should only take the mutex for the modification itself, and not for the entire computation (or, say, sensor reading):
for (i = 0; i < sensor_count; i++) {
value = read_sensor(i);
pthread_mutex_lock(&mutex);
sensor_reading[i] = value;
pthread_mutex_unlock(&mutex);
}
instead of pthread_mutex_lock(&mutex); sensor_reading[i] = read_sensor(i); pthread_mutex_unlock(&mutex);, because this latter would just hold the mutex while reading the sensor, blocking other threads' access to the array for the duration of the read_sensor(i) call for no sensible reason.
Simple assignment or arithmetic on the array element is not 'slow', and therefore the first function is the recommended pattern here.
In general, the pattern
for (i = 0; i < N; i++) {
pthread_mutex_lock(&mutex);
/* Do something */
pthread_mutex_unlock(&mutex);
}
only releases the mutex for a short duration, and depending on the pthreads implementation, it may not be long enough for any other thread to grab the mutex, even if they were already blocking/waiting on the mutex (in a pthread_mutex_lock(&mutex) call). It is not wrong or an error, though, it just works the same as
pthread_mutex_lock(&mutex);
for (i = 0; i < N; i++) {
/* Do something */
}
pthread_mutex_unlock(&mutex);
and is less efficient than this latter form, because the former does (N-1) extra pthread_mutex_lock() and pthread_mutex_unlock() calls, with no guarantees of any benefits of doing so.

Testing race condition

I just started learning about thread today, and wanted to test the race condition of threads by running two codes with/without mutex.
#define HAVE_STRUCT_TIMESPEC
#include <pthread.h>
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#define NTHREADS 3
#define ITERATIONS (long long) 1000000000
//pthread_mutex_t mutex;
static long long counter = 0;
static void * thread_f(void * arg) {
unsigned long long i;
(void)arg;
for (i = 0; i != ITERATIONS; i++) {
// pthread_mutex_lock(&mutex);
counter = counter + 1;
// pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(void) {
pthread_t threads[NTHREADS];
int i;
for (i = 0; i != NTHREADS; i++)
pthread_create(&threads[i], NULL, thread_f, NULL);
for (i = 0; i != NTHREADS; i++)
pthread_join(threads[i], NULL);
printf("expected = %lld, actual = %lld\n", NTHREADS*ITERATIONS, counter);
printf("experienced %lld race conditions\n", NTHREADS*ITERATIONS - counter);
system("pause");
return 0;
}
So, without mutex, the program prints out these following lines on cmd:
expected = 3000000000, actual = 1174158414
experienced 1825841586 race conditions
However, if I put mutex in the code, and run the program, cmd pops up then shuts down itself without showing any result.
I want to know if I coded anything wrong or is misusing mutex lines as I really don't know much about threads.
p.s this is coded in windows 10, using visual studio
Thanks to EOF from the comment, I found out that I did not initialize mutex in the code.
I simply added:
if (pthread_mutex_init(&mutex, NULL)) {
printf("Something went wrong\n");
return 1;
}
this in the main, and everything works fine now.

C - synchronizing multiple threads w/ mutexs

I'm trying to synchronize multiple (7) threads. I thought I understood how they work until I was trying it on my code and my threads were still printing out of order. Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
void *text(void *arg);
long code[] = {4,6,3,1,5,0,2}; //Order in which to start threads
int num = 0;
pthread_mutex_t lock; //Mutex variable
int main()
{
int i;
pthread_t tid[7];
//Check if mutex worked
if (pthread_mutex_init(&lock, NULL) != 0){
printf("Mutex init failed\n");
return 1;
}
//Initialize random number generator
time_t seconds;
time(&seconds);
srand((unsigned int) seconds);
//Create our threads
for (i=0; i<7; i++)
pthread_create(&tid[i], NULL, text, (void*)code[i]);
//Wait for threads to finish
for (i=0; i<7; i++){
if(pthread_join(tid[i], NULL)){
printf("A thread failed to join\n");
}
}
//Destroy mutex
pthread_mutex_destroy(&lock);
//Exit main
return 0;
}
void *text (void *arg)
{
//pthread_mutex_lock(&lock); //lock
long n = (long) arg;
int rand_sec = rand() % (3 - 1 + 1) + 1; //Random num seconds to sleep
while (num != n) {} //Busy wait used to wait for our turn
num++; //Let next thread go
sleep(rand_sec); //Sleep for random amount of time
pthread_mutex_lock(&lock); //lock
printf("This is thread %d.\n", n);
pthread_mutex_unlock(&lock); //unlock
//Exit thread
pthread_exit(0);
}
So here I am trying to make threads 0-6 print IN ORDER but right now they are still scrambled. The commented out mutex lock is where I originally had it, but then moved it down to the line above the print statement but I'm having similar results. I am not sure where the error in my mutex's are, could someone give a hint or point me in the right direction? I really appreciate it. Thanks in advance!
You cannot make threads to run in order with only a mutex because they go in execution in an unpredictable order.
In my approach I use a condition variable and a shared integer variable to create a queueing system. Each thread takes a number and when the current_n number is equal to the one of the actual thread, it enters the critical section and prints its number.
#include <pthread.h>
#include <stdio.h>
#define N_THREAD 7
int current_n = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t number = PTHREAD_COND_INITIALIZER;
void *text (void *arg) {
int i = (int)arg;
pthread_mutex_lock(&mutex);
while ( i > current_n ) {
pthread_cond_wait(&number, &mutex);
}
//i = current_n at this point
/*I use stderr because is not buffered and the output will be printed immediately.
Alternatively you can use printf and then fflush(stdout).
*/
fprintf(stderr, "I'm thread n=%d\n", i);
current_n ++;
pthread_cond_broadcast(&number);
pthread_mutex_unlock(&mutex);
return (void*)0;
}
int main() {
pthread_t tid[N_THREAD];
int i = 0;
for(i = 0; i < N_THREAD; i++) {
pthread_create(&tid[i], NULL, text, (void *)i);
}
for(i = 0; i < N_THREAD; i++) {
if(pthread_join(tid[i], NULL)) {
fprintf(stderr, "A thread failed to join\n");
}
}
return 0;
}
The output is:
I'm thread n=0
I'm thread n=1
I'm thread n=2
I'm thread n=3
I'm thread n=4
I'm thread n=5
I'm thread n=6
Compile with
gcc -Wall -Wextra -O2 test.c -o test -lpthread
Don't worry about the warnings.

Semaphores and Deadlocks in C

I'm trying to code the producer/consumer problem using semaphores. I have 3, 1 acting as a mutex, and another 2 for the buffer which the producers and consumers can add/remove from. When adding/removing from the buffer I use the binary semaphore to lock/unlock it so that the global variables aren't subject to any race conditions. The produce semaphore represents how many spots are available in the buffer (how many things can be put into the buffer) while the consumer semaphore represents how many things can be removed from the buffer. I think my logic is wrong cause I always reach a deadlock. Also when I removed the produce and consume semaphores just to test whether or not the program does what its supposed to do, I still get race conditions even though the binary semaphore should be blocking that. What am I doing wrong?
enter code here
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <pthread.h>
#include </usr/include/semaphore.h>
#define MAXITEMS 100
#define PRODUCER_NO 5
#define NUM_PRODUCED 5
void *producer_function (void);
void *consumer_function (void);
void add_buffer (long i);
long get_buffer ();
long sum_value = 0;
long finished_producers;
long buffer[MAXITEMS];
int size = 0;
int front, rear = 0;
pthread_t producerThread[5];
pthread_t consumerThread;
sem_t mutex, produce, consume;
int main(void)
{
int i = 0;
srand (time(NULL));
sem_init (&mutex, 0, 1);
sem_init (&produce, 0, 100);
sem_init (&consume, 0, 0);
for (i = 0; i < 5; i++)
{
pthread_create (&producerThread[i], NULL, (void *) producer_function, NULL);
}
pthread_create (&consumerThread, NULL, (void *) consumer_function, NULL);
for (i = 0; i < 5; i++)
{
pthread_join (producerThread[i], NULL);
}
pthread_join (consumerThread, NULL);
return(0);
}
void *producer_function(void)
{
long counter = 0;
long producer_sum = 0L;
while (counter < NUM_PRODUCED)
{
sem_wait (&mutex);
sem_wait (&produce);
long rndNum = rand() % 10;
producer_sum += rndNum;
add_buffer (rndNum);
sem_post (&consume);
counter++;
if (counter == NUM_PRODUCED)
{
finished_producers++;
}
sem_post (&mutex);
usleep(1000);
}
printf("--+---+----+----------+---------+---+--+---+------+----\n");
printf("The sum of produced items for this producer at the end is: %ld \n", producer_sum);
printf("--+---+----+----------+---------+---+--+---+------+----\n");
return(0);
}
void *consumer_function (void)
{
while (1)
{
sem_wait (&mutex);
sem_wait (&consume);
long readnum = get_buffer();
sem_post (&produce);
sum_value += readnum;
sem_post (&mutex);
//printf ("%ld\n", sum_value);
if ((finished_producers == PRODUCER_NO) && (size == 0))
{
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("The sum of the all produced items at the end is: %ld \n", sum_value);
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
break;
}
}
}
void add_buffer(long i){
buffer[rear] = i;
rear = (rear+1) % MAXITEMS;
size++;
}
long get_buffer(){
long v;
v = buffer[front];
front = (front+1) % MAXITEMS;
size--;
return v;
}
user2929779,
I think its essential to not have the mutex locked, when waiting for a consume notification in the consumer, or vice versa a produce notification in the producer. Imagine you're getting blocked because of waiting for a consume notification, and no producer was able to publish such a notification then your consumer keeps the mutex locked and no producer ever gets the chance to produce a new item...
So the order is important here:
1.) First wait for notification from remote side
2.) lock mutex
3.) modify global data
4.) release mutex
5.) notify remote side
Try this instead:
void *producer_function(void)
{
long counter = 0;
long producer_sum = 0L;
while (counter < NUM_PRODUCED)
{
sem_wait (&produce);
sem_wait (&mutex);
long rndNum = rand() % 10;
producer_sum += rndNum;
add_buffer (rndNum);
counter++;
if (counter == NUM_PRODUCED)
{
finished_producers++;
}
sem_post (&mutex);
sem_post (&consume);
usleep(1000);
}
printf("--+---+----+----------+---------+---+--+---+------+----\n");
printf("The sum of produced items for this producer at the end is: %ld \n", producer_sum);
printf("--+---+----+----------+---------+---+--+---+------+----\n");
return(0);
}
void *consumer_function (void)
{
while (1)
{
sem_wait (&consume);
sem_wait (&mutex);
long readnum = get_buffer();
sum_value += readnum;
if ((finished_producers == PRODUCER_NO) && (size == 0))
{
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("The sum of the all produced items at the end is: %ld \n", sum_value);
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
break;
}
sem_post (&mutex);
sem_post (&produce);
//printf ("%ld\n", sum_value);
}
return(0);
}
P.S. For now ignoring return values of system calls just to show example implementation...
P.S.S. See also pseudo code on wiki http://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem#Using_semaphores ...

Resources