pthread_join doesn't work - c

What I want to accomplish:
In the main function are created two threads. They increment a global variable with the number 5. And send a signal to consumer thread that decrements the variables.In the consumer thread between each decrementation the current value is displayed. The main thread has to wait until all the threads are finished and then exit.
What I get:
Some times the main function exits before the consumer had a chance to display the results. I'm using pthread_join, but it returns error code 3.
Any Ideas how to get the wanted results?
The code is bellow.
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
static pthread_mutex_t mtx;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *producer(void *arg);
void *consumer(void *arg);
static int avail = 0;
int main(int argc, char *argv[]){
pthread_t cons1, prod1, prod2;
int status;
int t1;
int t2;
int t3;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_mutexattr_t mtxAttr;
pthread_mutexattr_settype(&mtxAttr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mtx, &mtxAttr);
t1 = pthread_create(&prod1, &attr, producer, NULL);
if(t1 != 0){
perror("problem1");
}
t2 = pthread_create(&prod2, &attr, producer, NULL);
if(t2 != 0){
perror("problem2");
}
t3 = pthread_create(&cons1, &attr, consumer, NULL);
if(t3 != 0){
perror("problem3");
}
status = pthread_join(t1, NULL);
if(status != 0){
perror("can't join1");
}
status = pthread_join(t2, NULL);
if(status != 0){
perror("can't join2");
printf("\n%d\n", status);
}
status = pthread_join(t3, NULL);
if(status != 0){
printf("%s",strerror(errno));
}
printf("\nend result \t%d\n",avail);
printf("fin\n");
//while(1){}
return 0;
}
void *producer(void *arg){
int s;
printf("producer\n");
s = pthread_mutex_lock(&mtx);
avail+=5;
s = pthread_mutex_unlock(&mtx);
s = pthread_cond_signal(&cond);
pthread_exit(NULL);
}
void *consumer(void *arg){
int s;
while(1) {
s = pthread_mutex_lock(&mtx);
if(s !=0 ){
perror("lock err");
}
while (avail == 0) {
s = pthread_cond_wait(&cond, &mtx);
}
while (avail > 0) {
avail--;
printf("Temp: %d \n",avail);
}
s = pthread_mutex_unlock(&mtx);
}
printf("done");
pthread_exit(NULL);
}

Don't join on t1, t2 or t3. Those are the return codes of the pthread_create() function. Use pthread_join() on prod1, prod2 and cons1 instead. And please compile with -Wall -Wextra.

Related

Use semaphores in C to protect variable within for loop

I'm trying to use semaphores to avoid that a global variable is changed by threads and this variable is supposed to increment within the for loop. My main objective is to protect the variable cnt from the threads so it can increment within the for loop. However, I don't know how to do it because this is the first time I work with semaphores.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
sem_t semaphore;
int cnt = 0; //global shared variable
void *threadProd(void *param); //threads call this function.
int main(int argc, char *argv[])
{
int niters;
pthread_t tid1, tid2; //thread ids
sem_init(&semaphore,0,1);
if (argc != 2){
printf("Usage: %s <niters>\n", argv[0]);
exit(0);
}
niters = atoi(argv[1]);
pthread_create(&tid1, NULL, threadProd, &niters);
pthread_create(&tid2, NULL, threadProd, &niters);
pthread_join(tid1, NULL); //wait for thread to finish
pthread_join(tid2, NULL);
//check answer:
if(cnt != (2 * niters))
printf("Incorrect answer, cnt = %d\n", cnt);
else
printf("Correct answer, cnt = %d\n", cnt);
sem_destroy(&semaphore);
exit(0);
}
//Thread routine
void *threadProd(void *vargp)
{
sem_wait(&semaphore);
int upper = *((int *) vargp);
for (int i = 0; i < upper; i++)
cnt ++;
sem_post(&semaphore);
return NULL;
}

pthread_cancel() does not cancel a thread as it should

I am testing a signal handler for my OS Class project.
Basically my signal handler (which is running in it's own thread) have to handle SIGINT, this means that it has to "kill" all the other threads and then exit.
unfortunately my code does not work.
This is my dummy thread task, which I want to stop with a SIGINT
static void * dummyTask(){
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
while(1){
pthread_testcancel();
printf(" Hello!\n");
sleep(2);
}
return NULL;
}
Here is my main. As you can see I create the signal handler and then up to 2 dummy threads.
I save their thID in an array, I need this later in the task of the signal handler thread, as you will see
int main(){
//need to the signal handler thread, so it can kill all the threads with cancel
pthread_t **thids = malloc( 2 * sizeof(pthread_t *));
sigset_t set;
pthread_t signalHandlerThread;
sigemptyset(&set);
sigaddset(&set, SIGINT);
//s is for error checking, not importanto now
int s = pthread_sigmask(SIG_BLOCK, &set, NULL);
//shParam: signalHandlerParam
signalHParam *shParam = malloc(sizeof(signalHParam));
shParam->set = &set;
shParam->arrayOfThIDs = thids;
s = pthread_create(&signalHandlerThread, NULL, signalHandlerTask, (void *) shParam);
for(int i = 0; i < 2; i ++){
pthread_t dummyThread;
pthread_create(&dummyThread, NULL, &dummyTask, NULL);
thids[i] = &dummyThread;
}
pause();
//pthread_join(signalHandlerThread, NULL);
return 1;
}
As you can see the signalHandlerThread execute a function named signalHandlerTask, which is:
static void *signalHandlerTask(void *shParam){
signalHParam *tmp = (signalHParam *) shParam;
sigset_t *set = tmp->set;
int s, sig;
int i = sigismember(set, SIGINT);
if(i != 1)
printf("error\n");
while(1 == 1){
s = sigwait(set, &sig);
if(sig == SIGINT){
printf("\n----- signal recived ----\n");
//function that use the array to kill threads
killThreads(tmp->arrayOfThIDs);
pthread_exit(NULL); //kill the signal handler thread
}
}
}
The shParam is a struct that I use to pass multiple arguments to the task of the thread (signalHandlerTask) and it is like this
typedef struct{
pthread_t **arrayOfThIDs;
sigset_t *set;
} signalHParam;
Finally we are at the real issue. I created the killThreads function as follows:
void killThreads(pthread_t **thids){
for(int i = 0; i < 2; i++){
int r = pthread_cancel(*thids[i]);
if(r != 0)
printf("error!! %d\n", r);
//r is 3, why??
pthread_join(*thids[i], NULL);
}
}
The problem is, as said, that pthread_cancel(*thids[i]) not work, threads are left alive and I can't figure out why
Here is the entire code for those who wants to run it:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <error.h>
#include <unistd.h>
#include <errno.h>
typedef struct{
pthread_t **arrayOfThIDs;
sigset_t *set;
} signalHParam;
void killThreads(pthread_t **thids){
//termino il threadListener, e tutti i thread nel thread pool
for(int i = 0; i < 2; i++){
//FAI ANCHE SU PROGETTO!!
int r = pthread_cancel(*thids[i]);
if(r != 0)
printf("pthread_cancel failed: %s\n", strerror(r));
//FAI ANCHE SU PROGETTO!!
pthread_join(*thids[i], NULL);
}
}
static void *signalHandlerTask(void *shParam){
signalHParam *tmp = (signalHParam *) shParam;
sigset_t *set = tmp->set;
int s, sig;
int i = sigismember(set, SIGINT);
if(i != 1)
printf("error\n");
while(1 == 1){
s = sigwait(set, &sig);
if(sig == SIGINT){
printf("\n----- signal recived ----\n");
//function that use the array to kill threads
killThreads(tmp->arrayOfThIDs);
pthread_exit(NULL); //kill the signal handler thread
}
}
}
static void * dummyTask(){
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
//printf("mo aspetto 10s\n");
//sleep(10);
while(1){
pthread_testcancel();
printf(" Ciao!\n");
sleep(2);
}
return NULL;
}
int main(){
//need to the signal handler thread, so it can kill all the threads with cancel
pthread_t **thids = malloc( 2 * sizeof(pthread_t *));
sigset_t set;
pthread_t signalHandlerThread;
sigemptyset(&set);
sigaddset(&set, SIGINT);
//s is for error checking, not importanto now
int s = pthread_sigmask(SIG_BLOCK, &set, NULL);
//shParam: signalHandlerParam
signalHParam *shParam = malloc(sizeof(signalHParam));
shParam->set = &set;
shParam->arrayOfThIDs = thids;
s = pthread_create(&signalHandlerThread, NULL, signalHandlerTask, (void *) shParam);
for(int i = 0; i < 2; i ++){
pthread_t dummyThread;
pthread_create(&dummyThread, NULL, &dummyTask, NULL);
thids[i] = &dummyThread;
}
pthread_join(signalHandlerThread, NULL);
return 1;
}
Having run the full program myself, it turns out that the only important bug is the one I originally pointed out in the comments. (There are a bunch of style problems and places where I wouldn't have done it that way, but none of them rises to the level of "bug". There is one minor unrelated bug: you forgot to include stdio.h and signal.h.)
for(int i = 0; i < 2; i ++){
pthread_t dummyThread;
pthread_create(&dummyThread, NULL, &dummyTask, NULL);
thids[i] = &dummyThread;
}
This creates a single variable named dummyThread (whether or not it is declared inside the loop) and writes all of the thread handles into that variable. All of the thids[i] pointers are set to point to that one variable. Since a single pthread_t variable can only hold a single thread handle, you lose the thread handles created on all but the last iteration of the loop. Later, the signal handler thread will attempt to cancel the same thread repeatedly, will succeed the first time, and fail the remaining N-1 times. (To make it more obvious what's going on, increase the number of threads and notice that the program prints "pthread_cancel failed: No such process" exactly N-1 times, no matter what N is.)
The correction is simply to use an array of pthread_t instead of an array of pthread_t *, and write the thread handles directly into the array:
typedef struct{
pthread_t *arrayOfThIDs;
sigset_t *set;
} signalHParam;
void killThreads(pthread_t **thids){
//termino il threadListener, e tutti i thread nel thread pool
for(int i = 0; i < 2; i++){
//FAI ANCHE SU PROGETTO!!
int r = pthread_cancel(thids[i]);
if(r != 0)
printf("pthread_cancel failed: %s\n", strerror(r));
//FAI ANCHE SU PROGETTO!!
pthread_join(*thids[i], NULL);
}
}
// ...
int main(){
//need to the signal handler thread, so it can kill all the threads with cancel
pthread_t *thids = malloc( 2 * sizeof(pthread_t));
sigset_t set;
pthread_t signalHandlerThread;
sigemptyset(&set);
sigaddset(&set, SIGINT);
//s is for error checking, not importanto now
int s = pthread_sigmask(SIG_BLOCK, &set, NULL);
//shParam: signalHandlerParam
signalHParam *shParam = malloc(sizeof(signalHParam));
shParam->set = &set;
shParam->arrayOfThIDs = thids;
s = pthread_create(&signalHandlerThread, NULL, signalHandlerTask,
(void *) shParam);
for(int i = 0; i < 2; i ++){
pthread_create(&thids[i], NULL, &dummyTask, NULL);
}
pthread_join(signalHandlerThread, NULL);
return 1;
}
signalHandlerTask and dummyTask are basically correct as-is.

(C, pthreads) Let multiple threads synchronize and continue together

I have a program which consists of multiple threads.
These threads have to synchronize at some point, continue together, do their work of different lengths and then synchronize again.
Here's the example of what I mean:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_THREADS 10
void* thread(void* idp);
int threads_running = 0;
pthread_mutex_t* mutex;
pthread_cond_t* cond;
int main(int args, char **argv)
{
pthread_mutex_t mutex_var;
pthread_cond_t cond_var;
mutex = &mutex_var;
cond = &cond_var;
pthread_mutex_init(mutex, NULL);
pthread_cond_init(cond, NULL);
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++)
{
printf("Creating Thread %d....\n", i);
int* id = malloc(sizeof(int));
*id = i;
if(0 != pthread_create(&threads[i], NULL, thread, (void *) id))
{
perror("Error while creating the threads");
exit(1);
}
}
for (int i = 0; i < NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
void* thread(void* idp)
{
int* id = (int*) idp;
while (1)
{
sleep(*id+2); // Thread work
pthread_mutex_lock(mutex);
threads_running++;
pthread_mutex_unlock(mutex);
pthread_cond_broadcast(cond);
printf("Thread %d WAIT\n", *id);
fflush(stdout);
// Let threads synchronize
pthread_mutex_lock(mutex);
while(threads_running != NUM_THREADS)
{
pthread_cond_wait(cond, mutex);
}
pthread_mutex_unlock(mutex);
printf("Thread %d WAKEUP\n", *id);
fflush(stdout);
// and continue
pthread_mutex_lock(mutex);
threads_running--;
pthread_mutex_unlock(mutex);
}
}
The thing that happens, is that some (usually #9 and one or two others) reach Thread %d WAKEUP but before the others can wake-up threads_running is already smaller than NUM_THREADS.
How can I synchronize multiple threads, so they continue together?
I am having some trouble wrapping my head around the parallel accesses to variables.
I found the answer seconds later:
Change while(threads_running != NUM_THREADS) to while(threads_running != 0 && threads_running != NUM_THREADS)
Change threads_running--; to threads_running = 0;
Now it works perfectly.
I recommend using pthread_cond_signal() than pthread_cond_broadcast(cond);
So the code flow where while loop is exiting looks like below.
pthread_mutex_lock(mutex);
while(threads_running != 0 && threads_running != NUM_THREADS)
{
pthread_cond_wait(cond, mutex);
}
pthread_cond_signal(cond);
So the final code looks like this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_THREADS 10
void* thread(void* idp);
int threads_running = 0;
pthread_mutex_t* mutex;
pthread_cond_t* cond;
int main(int args, char **argv)
{
pthread_mutex_t mutex_var;
pthread_cond_t cond_var;
mutex = &mutex_var;
cond = &cond_var;
pthread_mutex_init(mutex, NULL);
pthread_cond_init(cond, NULL);
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++)
{
printf("Creating Thread %d....\n", i);
int* id = malloc(sizeof(int));
*id = i;
if(0 != pthread_create(&threads[i], NULL, thread, (void *) id))
{
perror("Error while creating the threads");
exit(1);
}
}
for (int i = 0; i < NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
void* thread(void* idp)
{
int* id = (int*) idp;
while (1)
{
sleep(*id+2); // Thread work
pthread_mutex_lock(mutex);
threads_running++;
pthread_mutex_unlock(mutex);
printf("Thread %d WAIT\n", *id);
fflush(stdout);
// Let threads synchronize
pthread_mutex_lock(mutex);
while(threads_running != 0 && threads_running != NUM_THREADS)
{
pthread_cond_wait(cond, mutex);
}
pthread_cond_signal(cond);
pthread_mutex_unlock(mutex);
printf("Thread %d WAKEUP\n", *id);
fflush(stdout);
// and continue
pthread_mutex_lock(mutex);
threads_running = 0;
pthread_mutex_unlock(mutex);
}
}

Not able to get mutex locks to prevent threads from accessing a function

Working on the Producer and Consumer problem for a class and having trouble just putting on the final touches. The problem I am encountering is that i think my mutex locks are not locking my threads out of the function. For example if I run the program and pass it the parameters 2 4 4 7 it would print 8 7's and then 2 seconds later it will print 8 8's and then 8 9's and so on. I have tried using trylock and moving around the semaphores but to no avail. Is there something that I am missing when that is causing none of the threads to be locked out?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
typedef int buffer_item;
#define BUFFER_SIZE 5
#define TRUE 1
buffer_item START_NUMBER;
int counter;
int insert_item(buffer_item item);
int remove_item(buffer_item *item);
buffer_item buffer[BUFFER_SIZE];
void* producer(void *ptr);
void* consumer(void *ptr);
pthread_cond_t condc, condp;
pthread_mutex_t mutex;
int sleepTime, producerThreads, consumerThreads,a;
pthread_attr_t attr;
sem_t full, empty;
int insert_item(buffer_item item)
{
if(counter < BUFFER_SIZE) {
buffer[counter] = item;
counter++;
return 0;
}
else {
return -1;
}
}
int remove_item(buffer_item *item)
{
if(counter > 0) {
*item = buffer[(counter-1)];
counter--;
return 0;
}
else {
return -1;
}
}
void* producer(void *ptr) {
buffer_item item;
item = START_NUMBER;
while(TRUE) {
sleep(sleepTime);
sem_wait(&empty);
pthread_mutex_lock(&mutex);
if(insert_item(item)) {
fprintf(stderr, "error \n");
}
else {
printf("producer%u produced %d\n", (unsigned int)pthread_self(),item);
item++;
}
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
}
void* consumer(void *ptr) {
buffer_item item;
while(TRUE) {
sleep(sleepTime);
sem_wait(&full);
pthread_mutex_lock(&mutex);
if(remove_item(&item)) {
fprintf(stderr, "error \n");
}
else {
printf("consumer%u consumed %d\n", (unsigned int)pthread_self(),item);
}
pthread_mutex_unlock(&mutex);
sem_post(&empty);
}
}
void initializeData() {
pthread_mutex_init(&mutex, NULL);
sem_init(&full, 0, 0);
sem_init(&empty, 0, BUFFER_SIZE);
pthread_attr_init(&attr);
counter = 0;
}
int main(int argc, char **argv) {
sleepTime = atoi(argv[1]);
producerThreads = atoi(argv[2]);
consumerThreads = atoi(argv[3]);
START_NUMBER = atoi(argv[4]);
initializeData();
pthread_t pro, con;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&condc, NULL);
pthread_cond_init(&condp, NULL);
for(a=0; a< consumerThreads;a++)
pthread_create(&con, NULL, consumer, NULL);
for(a=0;a<producerThreads;a++)
pthread_create(&pro, NULL, producer, NULL);
pthread_join(con, NULL);
pthread_join(pro, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&condc);
pthread_cond_destroy(&condp);
sleep(sleepTime);
}
Thanks for the help Dmitri, after moving around the lines you told me about and some discussion with one of my friends I finally got it to start outputting the right numbers!
This is the output i have been looking for
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
typedef int buffer_item;
#define BUFFER_SIZE 5
#define TRUE 1
buffer_item START_NUMBER;
buffer_item item;
int counter;
int insert_item(buffer_item item);
int remove_item(buffer_item *item);
buffer_item buffer[BUFFER_SIZE];
void* producer(void *ptr);
void* consumer(void *ptr);
pthread_cond_t condc, condp;
pthread_mutex_t mutex;
int sleepTime, producerThreads, consumerThreads, a, item;
pthread_attr_t attr;
sem_t full, empty;
int insert_item(buffer_item item)
{
if(counter < BUFFER_SIZE) {
buffer[counter] = item;
counter++;
return 0;
}
else {
return -1;
}
}
int remove_item(buffer_item *item)
{
if(counter > 0) {
*item = buffer[(counter-1)];
printf("consumer%u consumed %d\n", (unsigned int)pthread_self(),buffer[counter-1]);
counter--;
return 0;
}
else {
return -1;
}
}
void* producer(void *ptr) {
while(TRUE) {
sleep(sleepTime);
sem_wait(&empty);
pthread_mutex_lock(&mutex);
if(insert_item(START_NUMBER)) {
fprintf(stderr, "error \n");
}
else {
printf("producer%u produced %d\n", (unsigned int)pthread_self(),START_NUMBER);
START_NUMBER++;
}
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
}
void* consumer(void *ptr) {
while(TRUE) {
sleep(sleepTime);
sem_wait(&full);
pthread_mutex_lock(&mutex);
if(remove_item(&item)) {
fprintf(stderr, "error \n");
}
else {
// printf("consumer%u consumed %d\n", (unsigned int)pthread_self(),&START_NUMBER);
}
pthread_mutex_unlock(&mutex);
sem_post(&empty);
}
}
void initializeData() {
pthread_mutex_init(&mutex, NULL);
sem_init(&full, 0, 0);
sem_init(&empty, 0, BUFFER_SIZE);
pthread_attr_init(&attr);
counter = 0;
}
int main(int argc, char **argv) {
sleepTime = atoi(argv[1]);
producerThreads = atoi(argv[2]);
consumerThreads = atoi(argv[3]);
START_NUMBER = atoi(argv[4]);
item = START_NUMBER;
initializeData();
pthread_t pro, con;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&condc, NULL);
pthread_cond_init(&condp, NULL);
for(a=0; a< consumerThreads;a++)
pthread_create(&con, NULL, consumer, NULL);
for(a=0;a<producerThreads;a++)
pthread_create(&pro, NULL, producer, NULL);
pthread_join(con, NULL);
pthread_join(pro, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&condc);
pthread_cond_destroy(&condp);
sleep(sleepTime);
}

output value interleavely with two pthreads

I want to create two thread which output interleave like below
Thread1:1=>Ping!
Thread2:2=>Pong!
Thread1:3=>Ping!
Thread1:4=>Ping!
Thread2:5=>Pong!
Thread2:6=>Pong!
Thread1:7=>Ping!
Thread2:8=>Pong!
Thread1:9=>Ping!
..........
until 50
and my code is below
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
void* increment1(void* arg);
void* increment2(void* arg);
int count = 0;
sem_t sem;
int main() {
//variable initialize
pthread_t thread1, thread2;
int res1 = 0, res2 = 0;
int number = 0;
int i = 0;
//create semaphore
if (sem_init(&sem, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < 25; ++i){
//create thread
res1 = pthread_create(&thread1, NULL, increment1, NULL);
if (res1 != 0) {
printf("Thread1 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join( thread1, NULL);
res2 = pthread_create(&thread2, NULL, increment2, NULL);
if (res2 != 0) {
printf("Thread2 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join( thread2, NULL);
}
exit(EXIT_SUCCESS);
}
void* increment1(void* arg) {
sem_wait(&sem);
count ++;
printf("Thread1:%d\nPing!\n",count);
fsync(fileno(stdout));
sem_post(&sem);
}
void* increment2(void* arg) {
sem_wait(&sem);
count ++;
printf("Thread2:%d\nPong!\n",count);
fsync(fileno(stdout));
sem_post(&sem);
}
But I think that what I do isn't using two thread in parallel and is wrong, what I use is sequential alternative executing two thread and it isn't not in parallel.(By using pthread_join, thread2 will execute after thread1 finish).
I try to using semaphore it seem that it cannot assure the thread execution order.
What I want to ask is
1.how to using semaphore to assure the two thread order?
2.how to pause the thread and resume it? I think that I do is create new two pthread in a loop cycle.
Thank in advance.
Add a second semaphore and initialize it to zero so that thread1 is forced to first. Then increment1 and increment2 keep signally that it is the other threads turn to go. You had some minor hangups with where joined things that you can figure out.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
void* increment1(void* arg);
void* increment2(void* arg);
int count = 0;
sem_t sem1, sem2;
int main()
{
pthread_t thread[2];
int res = 0;
int number = 0;
int i = 0;
if (sem_init(&sem1, 0, 1) == -1)
{
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem2, 0, 0) == -1)
{
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < 25; ++i)
{
res = pthread_create(&thread[0], NULL, increment1, NULL);
if (res != 0)
{
printf("Thread creation failed!!\n");
exit(EXIT_FAILURE);
}
res = pthread_create(&thread[1], NULL, increment2, NULL);
if (res != 0)
{
printf("Thread creation failed!!\n");
exit(EXIT_FAILURE);
}
for (int j = 0; j < 2; ++j)
{
pthread_join(thread[j], NULL);
}
}
exit(EXIT_SUCCESS);
}
void* increment1(void* arg)
{
sem_wait(&sem1);
count ++;
printf("Thread1:%d Ping!\n", count);
fsync(fileno(stdout));
sem_post(&sem2);
}
void* increment2(void* arg)
{
sem_wait(&sem2);
count ++;
printf("Thread2:%d Pong!\n", count);
fsync(fileno(stdout));
sem_post(&sem1);
}
Thank for you guys, I have modified it and it seems fine.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
int count = 0;
void* increment_1(void* arg);
void* increment_2(void* arg);
sem_t sem_1, sem_2;
sem_t c_sem;
int main() {
//variable initialize
pthread_t thread1, thread2;
int res1 = 0, res2 = 0;
int number = 0;
int i = 0;
//create semaphore
if (sem_init(&c_sem, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem_1, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem_2, 0, 0) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
//create thread
res1 = pthread_create(&thread1, NULL, increment_1, NULL);
if (res1 != 0) {
printf("Thread1 creation failed!!\n");
exit(EXIT_FAILURE);
}
res2 = pthread_create(&thread2, NULL, increment_2, NULL);
if (res2 != 0) {
printf("Thread2 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
exit(EXIT_SUCCESS);
}
void* increment_1(void* arg) {
while(1){
sem_wait(&sem_1);
sem_wait(&c_sem);
if(count == 50){
sem_post(&c_sem);
sem_post(&sem_2);
exit(EXIT_SUCCESS);
}
count ++;
printf("Thread1:%d->Ping!\n",count);
fsync(fileno(stdout));
sem_post(&c_sem);
sem_post(&sem_2);
}
}
void* increment_2(void* arg) {
while(1){
sem_wait(&sem_2);
sem_wait(&c_sem);
if(count == 50){
sem_post(&c_sem);
sem_post(&sem_1);
exit(EXIT_SUCCESS);
}
count ++;
printf("Thread2:%d->Pong!\n",count);
fsync(fileno(stdout));
sem_post(&c_sem);
sem_post(&sem_1);
}
}

Resources