I created a simple program that shows the use of mutex lock. Here is the code...
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#define NUM_THREAD 2
pthread_mutex_t mutex;
int call_time;
void *makeCall(void *param)
{
call_time = 10;
pthread_mutex_lock(&mutex);
printf("Hi I'm thread #%u making a call\n", (unsigned int) pthread_self());
do{
printf("%d\n", call_time);
call_time--;
sleep(1);
}
while(call_time > 0);
pthread_mutex_unlock(&mutex);
return 0;
}
int main()
{
int i;
pthread_t thread[NUM_THREAD];
//init mutex
pthread_mutex_init(&mutex, NULL);
//create thread
for(i = 0; i < NUM_THREAD; i++)
pthread_create(&thread[i], NULL, makeCall, NULL);
//join thread
for(i = 0; i < NUM_THREAD; i++)
pthread_join(thread[i], NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
The output is...
Hi I'm thread #3404384000 making a call
10
10
9
8
7
6
5
4
3
2
1
Hi I'm thread #3412776704 making a call
0
However, if I modify the function makeCall and transfer the variable call_time inside the mutex locks...
pthread_mutex_lock(&mutex);
call_time = 10;
/*
*
*
*
*/
pthread_mutex_unlock(&mutex);
The program now gives me the correct output where each of the thread counts down from 10 to 0. I don't understand the difference it makes transferring the variable call_time inside the locks. I hope someone can make me understand this behavior of my program. Cheers!
call_time is a shared variable that is accessed from 2 threads and so must be protected. What is happening is that the first thread starts, sets call_time to 10 and prints the first round.Then the second thread starts, resets call_time back to 10 and waits for the mutex. The first thread now comes back and keeps running with call_time reset to 10. After it is done and frees the mutex, the second thread can now run. call_time is now 0 since the first thread left it at 0, and so it just prints the last round.
Try this program, I think it will demonstrate threads better:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#define NUM_THREAD 2
pthread_mutex_t mutex;
int call_time;
void *makeCall(void *param)
{
int temp;
do{
pthread_mutex_lock(&mutex);
printf("Hi I'm thread #%u making a call\n", (unsigned int) pthread_self());
printf("%d\n", call_time);
temp = call_time--;
pthread_mutex_unlock(&mutex);
//sleep(1); //try with and without this line and see the difference.
}
while(temp > 0);
return 0;
}
int main()
{
int i;
call_time = 100;
pthread_t thread[NUM_THREAD];
//init mutex
pthread_mutex_init(&mutex, NULL);
//create thread
for(i = 0; i < NUM_THREAD; i++)
pthread_create(&thread[i], NULL, makeCall, NULL);
//join thread
for(i = 0; i < NUM_THREAD; i++)
pthread_join(thread[i], NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
Related
I'm implementing a semaphore methods to understand synchronization and thread things.
By using my semaphore, I tried to solve the Dining Philosophers problem.
My plan was making deadlock situation first.
But I found that just only one philosopher eat repeatedly.
And I checked that my semaphore is working quite good by using other synchronization problems. I think there is some problem with grammar.
please let me know what is the problem.
Here is my code.
dinig.c (including main function)
#include "sem.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static tsem_t *chopstick[5];
static tsem_t *updating;
static int update_status (int i, int eating)
{
static int status[5] = { 0, };
static int duplicated;
int idx;
int sum;
tsem_wait (updating);
status[i] = eating;
/* Check invalid state. */
duplicated = 0;
sum = 0;
for (idx = 0; idx < 5; idx++)
{
sum += status[idx];
if (status[idx] && status[(idx + 1) % 5])
duplicated++;
}
/* Avoid printing empty table. */
if (sum == 0)
{
tsem_signal (updating);
return 0;
}
for (idx = 0; idx < 5; idx++)
fprintf (stdout, "%3s ", status[idx] ? "EAT" : "...");
/* Stop on invalid state. */
if (sum > 2 || duplicated > 0)
{
fprintf (stdout, "invalid %d (duplicated:%d)!\n", sum, duplicated);
exit (1);
}
else
fprintf (stdout, "\n");
tsem_signal (updating);
return 0;
}
void *thread_func (void *arg)
{
int i = (int) (long) arg;
int k = (i + 1) % 5;
do
{
tsem_wait (chopstick[i]);
tsem_wait (chopstick[k]);
update_status (i, 1);
update_status (i, 0);
tsem_signal (chopstick[i]);
tsem_signal (chopstick[k]);
}
while (1);
return NULL;
}
int main (int argc,
char **argv)
{
int i;
for (i = 0; i < 5; i++)
chopstick[i] = tsem_new (1);
updating = tsem_new (1);
for (i = 0; i < 5; i++)
{
pthread_t tid;
pthread_create (&tid, NULL, thread_func, (void *) (long) i);
}
/* endless thinking and eating... */
while (1)
usleep (10000000);
return 0;
}
sem.c(including semaphore methods)
#include "sem.h"
.
sem.h(Header for sem.c)
#ifndef __SEM_H__
#define __SEM_H__
#include <pthread.h>
typedef struct test_semaphore tsem_t;
tsem_t *tsem_new (int value);
void tsem_free (tsem_t *sem);
void tsem_wait (tsem_t *sem);
int tsem_try_wait (tsem_t *sem);
void tsem_signal (tsem_t *sem);
#endif /* __SEM_H__ */
compile command
gcc sem.c dining.c -pthread -o dining
One problem is that in tsem_wait() you have the following code sequence outside of a lock:
while(sem->count <= 0)
continue;
There's no guarantee that the program will actually re-read sem->count - the compiler is free to produce machine code that does something like the following:
int temp = sem->count;
while(temp <= 0)
continue;
In fact, this will likely happen in an optimized build.
Try changing your busy wait loop to something like this so the count is checked while holding the lock:
void tsem_wait (tsem_t *sem)
{
pthread_mutex_lock(&(sem->mutexLock));
while (sem->count <= 0) {
pthread_mutex_unlock(&(sem->mutexLock));
usleep(1);
pthread_mutex_lock(&(sem->mutexLock));
}
// sem->mutexLock is still held here...
sem->count--;
pthread_mutex_unlock(&(sem->mutexLock));
}
Strictly speaking, you should do something similar for tsem_try_wait() (which you're not using yet).
Note that you might want to consider using a pthread_cond_t to make waiting on the counter changing more efficient.
Finally, your code to 'get' the chopsticks in thread_func() has the classic Dining Philosopher deadlock problem in the situation where each philosopher simultaneously acquires the 'left' chopstick (chopstick[i]) and ends up waiting forever to get the 'right' chopstick (chopstick[k]) since all the chopsticks are in some philosopher's left hand.
I wrote a very simple test program to examine efficiency of pthread mutex. But I'm not able to analyse the results I get. (I can see 4 CPUs in Linux System Monitor and that's why I have at least 4 active threads, because I want to keep all of them busy.) The existence of mutex is not necessary in the code.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t lock1, lock2, lock3, lock4;
void do_sth() { /* just open a files, read it and copy to another file */
int i;
for (i = 0; i < 1; i++) {
FILE* fp = fopen("(2) Catching Fire.txt", "r");
if (fp == NULL) {
fprintf(stderr, "could not open file\n");
exit(1);
}
char filename[20];
sprintf(filename, "a%d", (int)pthread_self());
FILE* wfp = fopen(filename, "w");
if (wfp == NULL) {
fprintf(stderr, "could not open file for write\n");
exit(1);
}
int c;
while (c = fgetc(fp) != EOF) {
c++;
fputc(c, wfp);
}
close(fp);
close(wfp);
}
}
void* routine1(void* param) {
pthread_mutex_lock(&lock1);
do_sth();
pthread_mutex_unlock(&lock1);
}
void* routine2(void* param) {
pthread_mutex_lock(&lock2);
do_sth();
pthread_mutex_unlock(&lock2);
}
void* routine3(void* param) {
pthread_mutex_lock(&lock3);
do_sth();
pthread_mutex_unlock(&lock3);
}
void* routine4(void* param) {
pthread_mutex_lock(&lock4);
do_sth();
pthread_mutex_unlock(&lock4);
}
int main(int argc, char** argv) {
int i ;
pthread_mutex_init(&lock1, 0);
pthread_mutex_init(&lock2, 0);
pthread_mutex_init(&lock3, 0);
pthread_mutex_init(&lock4, 0);
pthread_t thread1[4];
pthread_t thread2[4];
pthread_t thread3[4];
pthread_t thread4[4];
for (i = 0; i < 4; i++)
pthread_create(&thread1[i], NULL, routine1, NULL);
for (i = 0; i < 4; i++)
pthread_create(&thread2[i], NULL, routine2, NULL);
for (i = 0; i < 4; i++)
pthread_create(&thread3[i], NULL, routine3, NULL);
for (i = 0; i < 4; i++)
pthread_create(&thread4[i], NULL, routine4, NULL);
for (i = 0; i < 4; i++)
pthread_join(thread1[i], NULL);
for (i = 0; i < 4; i++)
pthread_join(thread2[i], NULL);
for (i = 0; i < 4; i++)
pthread_join(thread3[i], NULL);
for (i = 0; i < 4; i++)
pthread_join(thread4[i], NULL);
printf("Hello, World!\n");
}
I execute this program in two ways, with and without all the mutex. and I measure time of execution (using time ./a.out) and average cpu load (using htop). here is the results:
first: when I use htop, I can see that loadavg of the system considerably increases when I do not use any mutex in the code. I have no idea why this happens. (is 4 active threads not enough to get the most out of 4 CPUs?)
second: It takes (a little) less time for the program to execute with all those mutex than without it. why does it happen? I mean, it should take some time to sleep and wake up a thread.
edit: I guess, when I use locks I put other threads to sleep and it eliminates a lot of context-switch (saving some time), could this be the reason?
You are using one lock per thread, so that's why when you use all the mutexes you don't see an increase in the execution time of the application: dosth() is not actually being protected from concurrent execution.
Since all the threads are working on the same file, all they should be accessing it using the same lock (otherwise you will have incorrect results: all the threads trying to modify the file at the same time).
Try running again the experiments using just one global lock.
I have a Thread which has to run every millisecond. When no other thread of the program is active, everything is fine. But if more than 3 other threads are running, the Timer-Thread is only called less than 100 times per second (on my test machine).
It seems that the priority settings of the Timer are ignored.
I have tested this with Kernel Versions 3.12 and 3.18.
Test code, which prints some values after 10000 calls of the timer thread (so normally after 10 seconds):
#define NTHREADS 3
#include <sched.h>
#include <pthread.h>
#include <signal.h>
timer_t timer;
unsigned long long val = 0;
pthread_attr_t attrHigh, attrLow;
void TimerTestThread()
{
val++;
if(val >= 10000)
printf("%i ", val);
}
void BusyThread()
{
int a;
while(1)
{
a++;
}
}
int main()
{
pthread_attr_init(&attrHigh);
pthread_attr_setinheritsched(&attrHigh, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attrHigh, SCHED_FIFO);
struct sched_param paramHigh;
paramHigh.sched_priority = 90;
pthread_attr_setschedparam(&attrHigh, ¶mHigh);
pthread_attr_init(&attrLow);
pthread_attr_setinheritsched(&attrLow, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attrLow, SCHED_FIFO);
struct sched_param paramLow;
paramLow.sched_priority = 1;
pthread_attr_setschedparam(&attrLow, ¶mLow);
struct sigevent evp;
evp.sigev_notify = SIGEV_THREAD;
evp.sigev_notify_function = TimerTestThread;
evp.sigev_notify_attributes = &attrHigh;
struct itimerspec value;
value.it_interval.tv_sec = 0; // Interval
value.it_interval.tv_nsec = 1000000;
value.it_value.tv_sec = 0; // Initial Expiration
value.it_value.tv_nsec = 1000000;
int i;
pthread_t threads[NTHREADS];
for(i=0; i<NTHREADS;i++)
{
pthread_create(&(threads[i]), &attrLow, BusyThread, NULL);
}
if(timer_create(CLOCK_MONOTONIC, &evp, &timer) != 0)
{
i = 5;
}
if(timer_settime(timer, 0, &value, NULL) != 0)
{
i = 6;
}
while(1);
}
I do not understand why the behavior is like this. Maybe you see something i missed.
EDIT: Corrected a silly source copy error
I have a simple threaded program which use a conditional variable and a rwlock. I've been staring at it for hours trying different approaches. The problem is that a thread or more stops at the rwlock after a while although it is not locked for writing. Maybe I miss something about how those locks work or how they are implemented.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <unistd.h>
//global variables
pthread_mutex_t mutex;
pthread_cond_t cond;
pthread_rwlock_t rwlock;
int counter;
int listLength = 1;
void* worker(void* arg){
do {
usleep(200);
printf("Before rwlock\n");
pthread_rwlock_rdlock(&rwlock);
printf("Before mutex\n");
pthread_mutex_lock(&mutex);
printf("Afer mutex\n");
counter++;
//signal the main
if (counter == 5 ||
(listLength < 5 && counter == listLength)){
printf("Signal main\n");
pthread_cond_signal(&cond);
counter = 0;
}
pthread_mutex_unlock(&mutex);
pthread_rwlock_unlock(&rwlock);
} while(listLength != 0);
return NULL;
}
int main(int argc, char* argv[]){
if (argc != 2){
perror("Invalid number of args");
exit(1);
}
//get arguments
int workers = atoi(argv[1]);
//initialize sync vars
pthread_rwlockattr_t attr;
pthread_rwlockattr_setkind_np(&attr,
PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_rwlock_init(&rwlock, &attr);
counter = 0;
//create threads
pthread_t threadArray[workers];
int threadOrder[workers];
for (int i = 0; i < workers; i++){
threadOrder[i] = i;
if (pthread_create(&threadArray[i], NULL,
worker, &threadOrder[i]) != 0){
perror("Cannot create thread");
exit(1);
}
}
while(listLength != 0) {
//wait for signal and lock the list
pthread_mutex_lock(&mutex);
while (pthread_cond_wait(&cond, &mutex) != 0);
pthread_rwlock_wrlock(&rwlock);
printf("In write lock\n");
pthread_mutex_unlock(&mutex);
pthread_rwlock_unlock(&rwlock);
printf("release wrlock\n");
}
//join the threads
for (int i = 0; i < workers; i++){
if (pthread_join(threadArray[i], NULL) !=0){
perror("Cannot join thread");
exit(1);
}
}
//release resources
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
pthread_rwlock_destroy(&rwlock);
return 0;
}
Looks like this code has several inconsistencies in it.
You're using mutex together with rwlock which means that all the threads of this kind are always locked. If you remove the rwlock code - it won't change the behaviour.
I cannot see the pthread_rwlock_init() call, and suppose you've called it in another place. Anyway pay attention you do call it and you don't call it twice or more times with the same rowlock object.
The same applies to pthread_rwlockattr_destroy()
I cannot see the reason why pthread_rwlock_rdlock() would block without write lock. Be sure you don't do it. Or else you could do a mutual lock of your mutex
I tried to find a solution in order to keep the number of working threads constant under linux in C using pthreads, but I seem to be unable to fully understand what's wrong with the following code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define MAX_JOBS 50
#define MAX_THREADS 5
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int jobs = MAX_JOBS;
int worker = 0;
int counter = 0;
void *functionC() {
pthread_mutex_lock(&mutex1);
worker++;
counter++;
printf("Counter value: %d\n",counter);
pthread_mutex_unlock(&mutex1);
// Do something...
sleep(4);
pthread_mutex_lock(&mutex1);
jobs--;
worker--;
printf(" >>> Job done: %d\n",jobs);
pthread_mutex_unlock(&mutex1);
}
int main(int argc, char *argv[]) {
int i=0, j=0;
pthread_t thread[MAX_JOBS];
// Create threads if the number of working threads doesn't exceed MAX_THREADS
while (1) {
if (worker > MAX_THREADS) {
printf(" +++ In queue: %d\n", worker);
sleep(1);
} else {
//printf(" +++ Creating new thread: %d\n", worker);
pthread_create(&thread[i], NULL, &functionC, NULL);
//printf("%d",worker);
i++;
}
if (i == MAX_JOBS) break;
}
// Wait all threads to finish
for (j=0;j<MAX_JOBS;j++) {
pthread_join(thread[j], NULL);
}
return(0);
}
A while (1) loop keeps creating threads if the number of working threads is under a certain threshold. A mutex is supposed to lock the critical sections every time the global counter of the working threads is incremented (thread creation) and decremented (job is done). I thought it could work fine and for the most part it does, but weird things happen...
For instance, if I comment (as it is in this snippet) the printf //printf(" +++ Creating new thread: %d\n", worker); the while (1) seems to generate a random number (18-25 in my experience) threads (functionC prints out "Counter value: from 1 to 18-25"...) at a time instead of respecting the IF condition inside the loop. If I include the printf the loop seems to behave "almost" in the right way... This seems to hint that there's a missing "mutex" condition that I should add to the loop in main() to effectively lock the thread when MAX_THREADS is reached but after changing a LOT of times this code for the past few days I'm a bit lost, now. What am I missing?
Please, let me know what I should change in order to keep the number of threads constant it doesn't seem that I'm too far from the solution... Hopefully... :-)
Thanks in advance!
Your problem is that worker is not incremented until the new thread actually starts and gets to run - in the meantime, the main thread loops around, checks workers, finds that it hasn't changed, and starts another thread. It can repeat this many times, creating far too many threads.
So, you need to increment worker in the main thread, when you've decided to create a new thread.
You have another problem - you should be using condition variables to let the main thread sleep until it should start another thread, not using a busy-wait loop with a sleep(1); in it. The complete fixed code would look like:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define MAX_JOBS 50
#define MAX_THREADS 5
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
int jobs = MAX_JOBS;
int workers = 0;
int counter = 0;
void *functionC() {
pthread_mutex_lock(&mutex1);
counter++;
printf("Counter value: %d\n",counter);
pthread_mutex_unlock(&mutex1);
// Do something...
sleep(4);
pthread_mutex_lock(&mutex1);
jobs--;
printf(" >>> Job done: %d\n",jobs);
/* Worker is about to exit, so decrement count and wakeup main thread */
workers--;
pthread_cond_signal(&cond1);
pthread_mutex_unlock(&mutex1);
return NULL;
}
int main(int argc, char *argv[]) {
int i=0, j=0;
pthread_t thread[MAX_JOBS];
// Create threads if the number of working threads doesn't exceed MAX_THREADS
while (i < MAX_JOBS) {
/* Block on condition variable until there are insufficient workers running */
pthread_mutex_lock(&mutex1);
while (workers >= MAX_THREADS)
pthread_cond_wait(&cond1, &mutex1);
/* Another worker will be running shortly */
workers++;
pthread_mutex_unlock(&mutex1);
pthread_create(&thread[i], NULL, &functionC, NULL);
i++;
}
// Wait all threads to finish
for (j=0;j<MAX_JOBS;j++) {
pthread_join(thread[j], NULL);
}
return(0);
}
Note that even though this works, it isn't ideal - it's best to create the number of threads you want up-front, and have them loop around, waiting for work. This is because creating and destroying threads has significant overhead, and because it often simplifies resource management. A version of your code rewritten to work like this would look like:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define MAX_JOBS 50
#define MAX_THREADS 5
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int jobs = MAX_JOBS;
int counter = 0;
void *functionC()
{
int running_job;
pthread_mutex_lock(&mutex1);
counter++;
printf("Counter value: %d\n",counter);
while (jobs > 0) {
running_job = jobs--;
pthread_mutex_unlock(&mutex1);
printf(" >>> Job starting: %d\n", running_job);
// Do something...
sleep(4);
printf(" >>> Job done: %d\n", running_job);
pthread_mutex_lock(&mutex1);
}
pthread_mutex_unlock(&mutex1);
return NULL;
}
int main(int argc, char *argv[]) {
int i;
pthread_t thread[MAX_THREADS];
for (i = 0; i < MAX_THREADS; i++)
pthread_create(&thread[i], NULL, &functionC, NULL);
// Wait all threads to finish
for (i = 0; i < MAX_THREADS; i++)
pthread_join(thread[i], NULL);
return 0;
}