I am writing a c program to create three threads(1,2,3) such that at any given point of time only one thread must execute and print the output on console in the order 123123123123.........
I am making use of semaphore for synchronization.
I am having an issue with the code i have written. the code doesn't print it in the order 123123... the order is random and stops after a while.
#include<stdio.h>
#include<semaphore.h>
#include<pthread.h>
#include<unistd.h>
#include<assert.h>
#include<stdlib.h>
sem_t sem_1;
void *func1(void *arg){
int err1=0;
while(1){
err1=sem_wait(&sem_1);
assert(err1==0);
printf("thread 1\n");
}
//return NULL;
}
void *func2(void *arg){
int err2=0;
while(1){
err2=sem_wait(&sem_1);
assert(err2==0);
printf("thread 2\n");
}
// return NULL;
}
void *func3(void *arg){
int err3=0;
while(1){
err3=sem_wait(&sem_1);
assert(err3==0);
printf("thread 3\n");
}
// return NULL;
}
int main(){
pthread_t *t1,*t2,*t3;
int i=0,rc=0,c1=0,c2=0,c3=0;
t1=(pthread_t *)malloc(sizeof(*t1));
t2=(pthread_t *)malloc(sizeof(*t2));
t3=(pthread_t *)malloc(sizeof(*t3));
i=sem_init(&sem_1,0,1);
assert(i==0);
c1=pthread_create(t1,NULL,func1,NULL);
assert(c1==0);
c2=pthread_create(t2,NULL,func2,NULL);
assert(c2==0);
c3=pthread_create(t3,NULL,func3,NULL);
assert(c3==0);
while(1){
rc=sem_post(&sem_1);
assert(rc==0);
sleep(1);
}
return 0;
}
Why would you even expect them in in an order?
Your threads do things inbetween the different waits, and according to the system scheduler, these can take different amount of time.
printf is a buffered operation that gives you exclusive access to a shared resource. So in addition to your semaphore there is a hidden lock somewhere, that also regulates the progress of your threads. Don't expect the prints to appear in order, even if the calls themselves are.
Then, for the end, using assert here is really a very bad idea. All sem_t operations can (and will) fail spuriously, so it is really bad to abort, just because such a failure.
In fact, sem_t is really a low level tool, and you should never use it without checking return values and without having a fall back strategy if such a call fails.
Of course. I can't see any order related synchronization mechanism.
One of the options to achieve the strict order is to have one semaphore per thread:
sem_t sem[3];
// ...
while(1) {
for(n = 0; n < 3; n++) {
rc=sem_post(&sem[n]);
assert(rc==0);
}
sleep(1);
}
Below Code will help to solve the problem, one semaphore for each thread used to achieve synchronization. The initial value of the semaphore does the job. used usleep to launch thread in sequence manner for needed output. The same can be done by using Mutex lock and cond variables
//declaring semaphore
sem_t sema1;
sem_t sema2;
sem_t sema3;
void* t1(void *arg)
{
for(int j=0;j<10;j++)
{
sem_wait(&sema1);
printf("Thread 1 \n");
sem_post(&sema2);
}
printf("T1 return\n");
return NULL;
}
void* t2(void *arg)
{
for(int j=0;j<10;j++)
{
sem_wait(&sema2);
printf("Thread 2 \n");
sem_post(&sema3);
}
printf("T2 return\n");
return NULL;
}
void* t3(void *arg)
{
for(int j=0;j<10;j++)
{
sem_wait(&sema3);
printf("Thread 3 \n");
sem_post(&sema1);
}
printf("T3 return \n");
return NULL;
}
int main()
{
pthread_t tid1, tid2,tid3;
sem_init(&sema1,0,1);
sem_init(&sema2,0,0);
sem_init(&sema3,0,0);
pthread_create(&tid1, NULL, t1, NULL);
usleep(100);
pthread_create(&tid2, NULL, t2, NULL);
usleep(100);
pthread_create(&tid3, NULL, t3, NULL);
pthread_join(tid3, NULL);
pthread_join(tid2, NULL);
pthread_join(tid1, NULL);
sem_destroy(&sema1);
sem_destroy(&sema2);
sem_destroy(&sema3);
return 0;
}
Related
Here is my code. The sum part is not working. I need some controls for that but I couldn't do it.
I tried make number variable number=-1, but that also didn't work and I had an infinite loop.
By the way this is my first question that i ask here, so i can make mistakes. Sorry for that.
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdbool.h>
int number = 0, sum = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *threadFunction1()
{
pthread_mutex_lock(&mutex);
while (true)
{
printf("Number:");
scanf("%d", &number);
if (number == 0) break;
}
pthread_exit(NULL);
}
void *threadFunction2()
{
pthread_mutex_lock(&mutex);
while (true)
{
sum += number;
printf("Sum is:%d\n", sum);
if (number == 0) break;
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main()
{
pthread_t thread1, thread2;
int case1, case2;
case1 = pthread_create(&thread1, NULL, threadFunction1, NULL);
case2 = pthread_create(&thread2, NULL, threadFunction2, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("It's over..\n");
pthread_mutex_destroy(&mutex);
return 0;
}
Here is the output
An immediately obvious issue is that threadFunction1 locks the mutex
pthread_mutex_lock(&mutex);
while (true)
{
printf("Number:");
scanf("%d", &number);
if (number == 0) break;
}
pthread_exit(NULL);
but never unlocks it. It is impossible to share a resource when one thread takes complete control over it.
The next issue is that the locking and unlocking of the mutex occurs outside of the while loop.
pthread_mutex_lock(&mutex);
while (true)
{
sum += number;
printf("Sum is:%d\n", sum);
if (number == 0) break;
}
pthread_mutex_unlock(&mutex);
This means whichever thread gets CPU time first will lock the mutex, and enter a potentially long running loop, only unlocking the mutex when that loop ends:
If threadFunction1 is the first to lock the mutex, this loop lasts until the user enters 0, wherein the loop is broken and the thread is terminated. After this, threadFunction2 never gets a turn, due to the lack of an unlock.
If threadFunction2 is the first to lock the mutex, this loop is broken after during its first iteration, as number is initialized to 0. After this the thread is terminated, and threadFunction1 would get a turn, since the mutex is unlocked.
The final issue is that a single mutex alone is not the correct tool to use here.
Even moving the locks and unlocks inside the loop, so that each thread has a chance to lock the mutex, do some work, and then unlock, there is no guarantee that both threads will get equal access to the lock.
while (true)
{
pthread_mutex_lock(&mutex);
sum += number;
printf("Sum is:%d\n", sum);
pthread_mutex_unlock(&mutex);
if (number == 0) break;
}
In fact, the opposite will probably occur. By default, it is very likely for one thread to be granted some CPU time, lock the mutex, do some work, unlock the mutex, and with its remaining time immediately lock the mutex again.
So we need a way to make two threads evenly share a resource.
One way is, instead of using a mutex, to use two semaphores to create a lockstep. This means one thread waits to for a semaphore which the other thread posts, and vice versa.
Note that in main we start the to_read semaphore with a value of 1, meaning the scanning thread effectively "goes first".
#include <pthread.h>
#include <semaphore.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
static int number = 0;
static int sum = 0;
static sem_t to_read;
static sem_t to_write;
static void *scanning(void *arg) {
while (true) {
sem_wait(&to_read);
printf("Enter a number: ");
if (1 != scanf("%d", &number))
number = 0;
sem_post(&to_write);
if (number == 0)
break;
}
return NULL;
}
static void *adding(void *arg) {
while (true) {
sem_wait(&to_write);
sum += number;
printf("Sum is: %d\n", sum);
sem_post(&to_read);
if (number == 0)
break;
}
return NULL;
}
int main(void) {
pthread_t thread1, thread2;
sem_init(&to_read, 0, 1);
sem_init(&to_write, 0, 0);
pthread_create(&thread1, NULL, scanning, NULL);
pthread_create(&thread2, NULL, adding, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
puts("It's over...");
sem_destroy(&to_read);
sem_destroy(&to_write);
}
Note that this will surely perform worse than a single threaded loop in main, doing the same amount of work, due to the overhead of context switching. That said, it is just a toy example.
I was writing 2 similar codes for printing odd and even numbers from given number set using mutex lock and semaphore. Both of the codes works fine.
But, while using mutex lock, even if I wont declare the pthread_mutex_init function, still the program executes with no issues. But that's not the case with semaphore. For this case, I have to declare sem_init in main() else the program execution gets stuck in sem_wait() (found after debugging).
So, how in the case of mutex lock, even without declaring init(), the program executes?
For reference, I am attaching the semaphore code.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
sem_t mutex;
pthread_t tid[2];
unsigned int shared_data[] = {23,45,67,44,56,78,91,102};
unsigned int rc;
int len=(sizeof(shared_data)/sizeof(shared_data[0]));
int i=0;
void *even(void *arg) {
rc = sem_wait(&mutex);
int temp = rc;
if(rc)
printf("Semaphore failed\n");
do{
if(shared_data[i] %2 == 0) {
printf("Even: %d\n",shared_data[i]);
i++;
}
else
rc = sem_post(&mutex);
}while(i<len);
}
void *odd(void *arg) {
rc = sem_wait(&mutex);
if(rc)
printf("Semaphore failed\n");
do {
if(shared_data[i] %2 != 0) {
printf("Odd: %d\n",shared_data[i]);
i++;
}
else
rc = sem_post(&mutex);
}while(i<len);
}
int main() {
sem_init(&mutex, 0,1);
pthread_create(&tid[0], 0, &even, 0);
pthread_create(&tid[1], 0, &odd, 0);
pthread_join(tid[0],NULL);
pthread_join(tid[1],NULL);
sem_destroy(&mutex);
return 0;
}
EDIT: Attaching the mutex lock code as well.
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
pthread_t tid[2];
unsigned int shared_data []= {23,45,67,44,56,78,91,102};
pthread_mutex_t mutex;
unsigned int rc;
int len=(sizeof(shared_data)/sizeof(shared_data[0]));
int i=0;
void* PrintEvenNos(void *ptr)
{
rc = pthread_mutex_lock(&mutex);
if(rc)
printf("Mutex lock has failed\n");
do
{
if(shared_data[i]%2 == 0)
{
printf("Even:%d\n",shared_data[i]);
i++;
} else {
rc=pthread_mutex_unlock(&mutex);
}
} while(i<len);
}
void* PrintOddNos(void* ptr1)
{
rc = pthread_mutex_lock(&mutex);
if(rc)
printf("Mutex lock has failed\n");
do
{
if(shared_data[i]%2 != 0)
{
printf("Odd:%d\n",shared_data[i]);
i++;
} else {
rc=pthread_mutex_unlock(&mutex);
}
} while(i<len);
}
void main(void)
{
pthread_create(&tid[0],0,PrintEvenNos,0);
pthread_create(&tid[1],0,PrintOddNos,0);
pthread_join(tid[0],NULL);
pthread_join(tid[1],NULL);
}
So, how in the case of mutex lock, even without declaring init(), the program executes?
This is undefined behavior, so there is no proper result. Per POSIX pthread_mutex_lock():
If mutex does not refer to an initialized mutex object, the behavior of pthread_mutex_lock(), pthread_mutex_trylock(), and pthread_mutex_unlock() is undefined.
"Appears to work" is one possible result of undefined behavior.
You have sem_init call for sem_t mutex;.
But pthread_mutex_init call is missing for pthread_mutex_t mutex;.
Both of the codes works fine.
No they don't; but first:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
Is how you should have initialized your mutex. On your system, this value might be zero, which would be equivalent to what you have. Either way, the problem is your program is broken.
One of your threads (even, odd) acquires a lock. In the case of even, when i is 0,1,2,5 or 6; you unlock it, which would permit odd() to proceed. In the case of odd, when i is 3,4,5 or 7, you unlock it, which would permit even() to proceed. So in your logic, the lock does nothing at all.
Also, semaphores are counters; so when you release it 5 times, you are permitting the next 5 sem_waits to proceed. Simple mutexes are gates, so only the first unlock has any effect, the subsequent 4 are errors. You don't check the error status of the unlock, which is typically the one that uncovers logic errors.
fwiw, on macos, the pthread_mutex_lock()'s both report an error.
I am working with pthreads right now doing the producer/consumer problem. I am currently just trying to get the producer working and using printf statements to see where my issues are. The problem is the code compiles just fine but when I run it, it doesn't do anything but seems to run just fine. I have tried setting my first line to a printf statement but even that does not print. I have tried using fflush as well and I am running out of ideas. My question why would even the first printf statement get skipped?
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
void *producer();
pthread_mutex_t lock;
pthread_cond_t done, full, empty;
int buffer[10];
int in = 0, out = 0;
int min = 0, max = 0, numOfItems = 0, total = 0;
double avg;
void *producer() {
srand(time(NULL));
int n = rand();
int i;
for(i = 0; i < n; i++)
{
int random = rand();
pthread_mutex_lock(&lock);
buffer[in++] = random;
if(in == 10)
{
pthread_cond_signal(&full);
printf("Buffer full");
pthread_mutex_unlock(&lock);
sleep(1);
}
}
pthread_exit(NULL);
}
void *consumer() {
pthread_exit(NULL);
}
int main(int argc, char *argv[]){
printf("test");
//Create threads and attribute
pthread_t ptid, ctid;
pthread_attr_t attr;
//Initialize conditions and mutex
pthread_cond_init(&full, NULL);
pthread_cond_init(&empty, NULL);
pthread_cond_init(&done, NULL);
pthread_mutex_init(&lock, NULL);
//Create joinable state
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&ptid, &attr,(void *)producer,NULL);
pthread_create(&ctid, &attr,(void *)consumer,NULL);
pthread_join(ptid,NULL);
pthread_join(ctid,NULL);
printf("Program Finished!");
pthread_exit(NULL);
}
man pthread_mutex_init
pthread_mutex_init initializes the mutex object pointed to by mutex
according to the mutex attributes specified in mutexattr. If mutexattr
is NULL, default attributes are used instead.
The LinuxThreads implementation supports only one mutex attributes, the
mutex kind... The kind of a mutex determines whether it can be locked again by
a thread that already owns it. The default kind is fast...
If the mutex is already locked by the calling thread, the behavior of
pthread_mutex_lock depends on the kind of the mutex. If the mutex is of
the fast kind, the calling thread is suspended until the mutex is
unlocked, thus effectively causing the calling thread to deadlock.
That's what happens to your producer: it deadlocks in the call
pthread_mutex_lock(&lock);
- except in the unlikely case n < 2 - thus producing no output.
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
int global;
int i = 30;
int j = 30;
int k = 30;
pthread_mutex_t mutex;
void* child1(void* arg)
{
while(k--)
{
pthread_mutex_lock(&mutex);
global++;
printf("from child1\n");
printf("%d\n",global);
pthread_mutex_unlock(&mutex);
}
}
void* child2(void* arg)
{
while(j--)
{
pthread_mutex_lock(&mutex);
global++;
printf("from child1\n");
printf("%d\n",global);
pthread_mutex_unlock(&mutex);
}
}
int main()
{
pthread_t tid1, tid2;
pthread_mutex_init(&mutex, NULL);
pthread_create(&tid1, NULL, child1, NULL);
pthread_create(&tid2, NULL, child2, NULL);
while(i--)
{
pthread_mutex_lock(&mutex);
global++;
printf("from main\n");
printf("%d\n",global);
pthread_mutex_unlock(&mutex);
}
return 0;
}
I'm new to pthread and multithreading, the result of this code is from main xx and child1 appeared rarely, the three threads never appear together, what's the problem?
Most of time in the critical sections will be spent in the printf calls. You might try:
{
int local;
pthread_mutex_lock(& mutex);
local = ++global;
pthread_mutex_unlock(& mutex);
printf("from <fn>\n%d\n", local);
}
This still doesn't give any guarantee of 'fairness' however, but the printf call is very likely to use a system call or I/O event that will cause the scheduler to kick in.
Your program is similar to the Dining Philosophers Problem in many respects. You don't want any thread to 'starve', but you have contention between threads for the global counter, and you want to enforce an orderly execution.
One suggestion in code replace printf("from child1\n"); to printf("from child2\n"); in void* child2(void* arg) function. And if you want ensure all threads to complete please add the following lines at end of main function.
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
I think you should use 3 differents mutex , by the way use pconditional control in order to avoid having unsafe access
I have 4 threads to create thread1, thread2, thread3 and thread4:
pthread_create(thread1,NULL,thread_func1,NULL);
pthread_create(thread2,NULL,thread_func2,NULL);
pthread_create(thread3,NULL,thread_func3,NULL);
pthread_create(thread4,NULL,thread_func4,NULL);
looking in the debug , The order of launched threads is not the same as defined in the source code.
Are there a solution to launch the threads with an order that I could define?
The launch order is sequential, in that the create calls happen in the order they're written.
However the scheduler for whatever reason isn't scheduling the newly launched threads in the order you hoped. If the order matters perhaps threads isn't what you want? The big advantage with threads is that they don't always get scheduled in a sequential order!
If you really want though you can use synchronisation primitives (e.g. a series of mutexes, or a condvar) to ensure that up to a certain point happens in predictable order, but from that point onwards the order will still be down to the whims of the scheduler. As an example this code guarantees that each thread will print its ID in the order they were created:
#include <pthread.h>
#include <stdio.h>
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void sync_threads(const int num, int *cur) {
pthread_mutex_lock(&mut);
while (*cur != num) {
pthread_cond_wait(&cond, &mut);
}
// Do work that must happen in order here:
printf("Thread: %d\n", num);
++*cur;
pthread_mutex_unlock(&mut);
pthread_cond_broadcast(&cond);
}
static int num = 1;
void *thread1(void *d) {
sync_threads(1,&num);
while (1); // Rest of work happens whenever
return NULL;
}
void *thread2(void *d) {
sync_threads(2,&num);
while (1);
return NULL;
}
void *thread3(void *d) {
sync_threads(3,&num);
while (1);
return NULL;
}
void *thread4(void *d) {
sync_threads(4,&num);
while (1);
return NULL;
}
int main() {
pthread_t t1,t2,t3,t4;
pthread_create(&t1, NULL, thread1, NULL);
pthread_create(&t2, NULL, thread2, NULL);
pthread_create(&t3, NULL, thread3, NULL);
pthread_create(&t4, NULL, thread4, NULL);
while(1) {
// some work
}
}
I've used while(1); to simulate some real work happening. It does this with a mutex protecting the "current" thread, i.e. the order of initialisation and then a condvar to make sleeping/waking possible. It broadcasts to all threads who then check to see which one is up next. You could design as system that skips the broadcast, but that complicates things for relatively little gain.
You can also add more synchronisation if required at other points, but the more you synchronise things the less point there is in having threads in the first place.
Ideally if things need to happen in a predictable order they should be done before spawning threads, not as soon as the threads spawn, e.g.:
fixed_init_for_thread1();
fixed_init_for_thread2();
fixed_init_for_thread3();
fixed_init_for_thread4();
pthread_create(thread1,NULL,thread_func1,NULL);
pthread_create(thread2,NULL,thread_func2,NULL);
pthread_create(thread3,NULL,thread_func3,NULL);
pthread_create(thread4,NULL,thread_func4,NULL);
such that by the time the threads are created you don't care which one actually gets given the chance to run first.
I don't think you really care which thread executed first. If you just need an unique identifier for the four threads, check pthread_self. To have sequential IDs, call the ID allocator from within the thread; or generate the ID and pass it as user parameter when calling pthread_create.
here after the solution I used
#include <pthread.h>
#include <stdio.h>
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static bool wait = TRUE;
void thread_sync() {
pthread_mutex_lock(&mut);
wait = FALSE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mut);
}
void thread_wait_sync() {
pthread_mutex_lock(&mut);
if (wait==TRUE)
{
pthread_cond_wait(&cond,&mut);
}
wait = TRUE;
pthread_mutex_unlock(&mut);
}
void *thread1(void *d) {
thread_sync();
while (1); // Rest of work happens whenever
return NULL;
}
void *thread2(void *d) {
thread_sync();
while (1);
return NULL;
}
void *thread3(void *d) {
thread_sync();
while (1);
return NULL;
}
void *thread4(void *d) {
while (1);
return NULL;
}
int main() {
pthread_t t1,t2,t3,t4;
pthread_create(&t1, NULL, thread1, NULL);
thread_wait_sync();
pthread_create(&t2, NULL, thread2, NULL);
thread_wait_sync();
pthread_create(&t3, NULL, thread3, NULL);
thread_wait_sync();
pthread_create(&t4, NULL, thread4, NULL);
while(1) {
// some work
}
}
Move 'pthread_create(thread2,NULL,thread_func2,NULL);' into thread_func1()
Move 'pthread_create(thread3,NULL,thread_func2,NULL);' into thread_func2()
Move 'pthread_create(thread4,NULL,thread_func2,NULL);' into thread_func3()
This is VERY close to the other question posted recently and just as err.. 'strange'