Pthread query: Sequence of threads error - c++

#include<pthread.h>
#include<stdio.h>
int num_threads=3;
int state=0;
pthread_cond_t cond;
pthread_mutex_t mutex;
void* threadA(void* args) {
int i;
for(i=0; i<5; i++){
pthread_mutex_lock(&mutex);
while(state == 1 || state == 2) pthread_cond_wait(&cond,&mutex);
printf("Thread A\n");
state = (state+1)%num_threads;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
void* threadB(void* args) {
int i;
for(i=0; i<5; i++){
pthread_mutex_lock(&mutex);
while(state == 0 || state == 2)pthread_cond_wait(&cond,&mutex);
printf("Thread B\n");
state = (state+1)%num_threads;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
void* threadC(void* args) {
int i;
for(i=0; i<5; i++){
pthread_mutex_lock(&mutex);
while(state == 1 || state == 0) pthread_cond_wait(&cond,&mutex);
printf("Thread C\n\n");
state = (state+1)%num_threads;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
int main() {
pthread_t tid[3];
pthread_cond_init(&cond,NULL);
pthread_mutex_init(&mutex,NULL);
pthread_create(&tid[0],NULL,threadA,NULL);
pthread_create(&tid[1],NULL,threadB,NULL);
pthread_create(&tid[2],NULL,threadC,NULL);
return 0;
}
QUESTION: With the above code, I wish to print
threaA threadB threadC sequentially 5 times.
But the answer is undeterministic. While the order
of threads is maintained, answers are not printed 5 times.
Please help!!!

As #mch mentioned in the comment, you need to wait for the threads to finish before allowing the main() function to return:
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
pthread_join(tid[2], NULL);
Now, after you add the joins above to the end of main(), your program will most often hang. This happens because the pthread_cond_signal() doesn't wake up all threads waiting on that condition variable. If the wrong thread is woke up (e.g. threadC signals the condition, but the thread that gets notified is not threadA), then all threads will be waiting on the condition and there will be nobody to signal that condition.
To fix this, you need to make sure all threads are woke up each time and let each thread decide on it's own if it is its turn or not (by that while(state...) pthread_cond_wait(...);). To do this, you can replace the calls to pthread_cond_signal() with calls to pthread_cond_broadcast(), which unblocks all threads currently blocked on that condition.

Related

A semaphore implmentation with Peterson's N process algorithm

I need feedback on my code for following statement, am I on right path?
Problem statement:
a. Implement a semaphore class that has a private int and three public methods: init, wait and signal. The wait and signal methods should behave as expected from a semaphore and must use Peterson's N process algorithm in their implementation.
b. Write a program that creates 5 threads that concurrently update the value of a shared integer and use an object of semaphore class created in part a) to ensure the correctness of the concurrent updates.
Here is my working program:
#include <iostream>
#include <pthread.h>
using namespace std;
pthread_mutex_t mid; //muted id
int shared=0; //global shared variable
class semaphore {
int counter;
public:
semaphore(){
}
void init(){
counter=1; //initialise counter 1 to get first thread access
}
void wait(){
pthread_mutex_lock(&mid); //lock the mutex here
while(1){
if(counter>0){ //check for counter value
counter--; //decrement counter
break; //break the loop
}
}
pthread_mutex_unlock(&mid); //unlock mutex here
}
void signal(){
pthread_mutex_lock(&mid); //lock the mutex here
counter++; //increment counter
pthread_mutex_unlock(&mid); //unlock mutex here
}
};
semaphore sm;
void* fun(void* id)
{
sm.wait(); //call semaphore wait
shared++; //increment shared variable
cout<<"Inside thread "<<shared<<endl;
sm.signal(); //call signal to semaphore
}
int main() {
pthread_t id[5]; //thread ids for 5 threads
sm.init();
int i;
for(i=0;i<5;i++) //create 5 threads
pthread_create(&id[i],NULL,fun,NULL);
for(i=0;i<5;i++)
pthread_join(id[i],NULL); //join 5 threads to complete their task
cout<<"Outside thread "<<shared<<endl;//final value of shared variable
return 0;
}
You need to release the mutex while spinning in the wait loop.
The test happens to work because the threads very likely run their functions start to finish before there is any context switch, and hence each one finishes before the next one even starts. So you have no contention over the semaphore. If you did, they'd get stuck with one waiter spinning with the mutex held, preventing anyone from accessing the counter and hence release the spinner.
Here's an example that works (though it may still have an initialization race that causes it to sporadically not launch correctly). It looks more complicated, mainly because it uses the gcc built-in atomic operations. These are needed whenever you have more than a single core, since each core has its own cache. Declaring the counters 'volatile' only helps with compiler optimization - for what is effectively SMP, cache consistency requires cross-processor cache invalidation, which means special processor instructions need to be used. You can try replacing them with e.g. counter++ and counter-- (and same for 'shared') - and observe how on a multi-core CPU it won't work. (For more details on the gcc atomic ops, see https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/_005f_005fatomic-Builtins.html)
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdint.h>
class semaphore {
pthread_mutex_t lock;
int32_t counter;
public:
semaphore() {
init();
}
void init() {
counter = 1; //initialise counter 1 to get first access
}
void spinwait() {
while (true) {
// Spin, waiting until we see a positive counter
while (__atomic_load_n(&counter, __ATOMIC_SEQ_CST) <= 0)
;
pthread_mutex_lock(&lock);
if (__atomic_load_n(&counter, __ATOMIC_SEQ_CST) <= 0) {
// Someone else stole the count from under us or it was
// a fluke - keep trying
pthread_mutex_unlock(&lock);
continue;
}
// It's ours
__atomic_fetch_add(&counter, -1, __ATOMIC_SEQ_CST);
pthread_mutex_unlock(&lock);
return;
}
}
void signal() {
pthread_mutex_lock(&lock); //lock the mutex here
__atomic_fetch_add(&counter, 1, __ATOMIC_SEQ_CST);
pthread_mutex_unlock(&lock); //unlock mutex here
}
};
enum {
NUM_TEST_THREADS = 5,
NUM_BANGS = 1000
};
// Making semaphore sm volatile would be complicated, because the
// pthread_mutex library calls don't expect volatile arguments.
int shared = 0; // Global shared variable
semaphore sm; // Semaphore protecting shared variable
volatile int num_workers = 0; // So we can wait until we have N threads
void* fun(void* id)
{
usleep(100000); // 0.1s. Encourage context switch.
const int worker = (intptr_t)id + 1;
printf("Worker %d ready\n", worker);
// Spin, waiting for all workers to be in a runnable state. These printouts
// could be out of order.
++num_workers;
while (num_workers < NUM_TEST_THREADS)
;
// Go!
// Bang on the semaphore. Odd workers increment, even decrement.
if (worker & 1) {
for (int n = 0; n < NUM_BANGS; ++n) {
sm.spinwait();
__atomic_fetch_add(&shared, 1, __ATOMIC_SEQ_CST);
sm.signal();
}
} else {
for (int n = 0; n < NUM_BANGS; ++n) {
sm.spinwait();
__atomic_fetch_add(&shared, -1, __ATOMIC_SEQ_CST);
sm.signal();
}
}
printf("Worker %d done\n", worker);
return NULL;
}
int main() {
pthread_t id[NUM_TEST_THREADS]; //thread ids
// create test worker threads
for(int i = 0; i < NUM_TEST_THREADS; i++)
pthread_create(&id[i], NULL, fun, (void*)((intptr_t)(i)));
// join threads to complete their task
for(int i = 0; i < NUM_TEST_THREADS; i++)
pthread_join(id[i], NULL);
//final value of shared variable. For an odd number of
// workers this is the loop count, NUM_BANGS
printf("Test done. Final value: %d\n", shared);
const int expected = (NUM_TEST_THREADS & 1) ? NUM_BANGS : 0;
if (shared == expected) {
puts("PASS");
} else {
printf("Value expected was: %d\nFAIL\n", expected);
}
return 0;
}

C++ threads: cannot unlock mutex in array after condition_variable wait

I am trying to synchronize one main thread with N children threads. After some reading, I used condition_variable and unique_lock. However, I always get the errors condition_variable::wait: mutex not locked: Operation not permitted or unique_lock::unlock: not locked: Operation not permitted, in OS X. In Linux, I get Operation not permitted only.
To be clearer: my goal is to get a sequence of prints:
main thread, passing to 0
thread 0, passing back to main
main thread, passing to 0
thread 0, passing back to main
...
for each of the four threads.
I adapted the code from the example in http://en.cppreference.com/w/cpp/thread/condition_variable. This example uses unlock after wait, and it works wonderfully with only one thread other than main (N=1). But when adapted to work with N>1 threads, the error above happens.
Yam Marcovic said in the comments that I should not use unlock. But then, why does the cppreference example use it? And why does it work well with one main and one other threads?
Here is the code:
#include <cstdio>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
constexpr int N_THREADS = 4;
constexpr int N_ITER = 10;
bool in_main[N_THREADS] = {false};
void fun(mutex *const mtx, condition_variable *const cv, int tid){
for(int i=0; i<N_ITER; i++) {
unique_lock<mutex> lk(*mtx);
// Wait until in_main[tid] is false
cv->wait(lk, [=]{return !in_main[tid];});
// After the wait we own the lock on mtx, which is in lk
printf("thread %d, passing back to main\n", tid);
in_main[tid] = true;
lk.unlock(); // error here, but example uses unlock
cv->notify_one();
}
}
int main(int argc, char *argv[]) {
// We are going to create N_THREADS threads. Create mutexes and
// condition_variables for all of them.
mutex mtx[N_THREADS];
condition_variable cv[N_THREADS];
thread t[N_THREADS];
// Create N_THREADS unique_locks for using the condition_variable with each
// thread
unique_lock<mutex> lk[N_THREADS];
for(int i=0; i<N_THREADS; i++) {
lk[i] = unique_lock<mutex>(mtx[i]);
// Create the new thread, giving it its thread id, the mutex and the
// condition_variable,
t[i] = thread(fun, &mtx[i], &cv[i], i);
}
for(int i=0; i < N_ITER*N_THREADS; i++) {
int tid=i % N_THREADS; // Thread id
// Wait until in_main[tid] is true
cv[tid].wait(lk[tid], [=]{return in_main[tid];});
// After the wait we own the lock on mtx[tid], which is in lk[tid]
printf("main thread, passing to %d\n", tid);
in_main[tid] = false;
lk[tid].unlock(); // error here, but example uses unlock
cv[tid].notify_one();
}
for(int i=0; i<N_THREADS; i++)
t[i].join();
return 0;
}
Sample output:
thread 0, passing back to main
main thread, passing to 0
thread 1, passing back to main
thread 0, passing back to main
main thread, passing to 1
thread 2, passing back to main
thread 1, passing back to main
main thread, passing to 2
thread 2, passing back to main
thread 3, passing back to main
main thread, passing to 3
main thread, passing to 0
thread 3, passing back to main
libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: unique_lock::unlock: not locked: Operation not permitted
Abort trap: 6
you are trying to unlock your mutexes many times! look at the code carefully:
for(int i=0; i < N_ITER*N_THREADS; i++) {
int tid=i % N_THREADS; // Thread id
where N_ITER is 10 and N_THREADS is 4 always, because they are constexpr
we get:
for(int i=0; i < 40; i++) {
int tid=i % 4; // Thread id
so, when i = 0 the mutex in lk[0] is unlocked, and then when i=4 then tid = 4%4 so again tid = 0 and you are unlocking it again! std::system_error is thrown in this case.
plus, why are all of these C-Pointers anyway? it's not like anyof them can be null at any time.. switch to references..
also, usually when dealing with array indexes the convention is to use size_t and not int.
I found what the problem is. This question Using std::mutex, std::condition_variable and std::unique_lock helped me.
Constructing a unique_lock is acquiring the unique_lock too. So it must be done inside the loop, just before calling wait. The function fun looks the same, but main now looks like this:
int main(int argc, char *argv[]) {
// We are going to create N_THREADS threads. Create mutexes and
// condition_variables for all of them.
mutex mtx[N_THREADS];
condition_variable cv[N_THREADS];
thread t[N_THREADS];
// Create N_THREADS unique_locks for using the condition_variable with each
// thread
for(int i=0; i<N_THREADS; i++) {
// Create the new thread, giving it its thread id, the mutex and the
// condition_variable,
t[i] = thread(fun, &mtx[i], &cv[i], i);
// DO NOT construct, therefore acquire, a unique_lock
}
for(int i=0; i < N_ITER*N_THREADS; i++) {
int tid=i % N_THREADS; // Thread id
// Acquire the unique_lock here
unique_lock<mutex> lk(mtx[tid]);
// Wait until in_main[tid] is true
cv[tid].wait(lk, [=]{return in_main[tid];});
// After the wait we own the lock on mtx[tid], which is in lk[tid]
printf("main thread, passing to %d\n", tid);
in_main[tid] = false;
lk.unlock(); // error here, but example uses unlock
cv[tid].notify_one();
}
for(int i=0; i<N_THREADS; i++)
t[i].join();
return 0;
}
The only difference is that the unique_lock is constructed inside the loop.

why does pthread_cond_signal cause deadlock

I am new to conditional variables and get deadlock if not using pthread_cond_broadcast().
#include <iostream>
#include <pthread.h>
pthread_mutex_t m_mut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
bool ready = false;
void* print_id (void *ptr )
{
pthread_mutex_lock(&m_mut);
while (!ready) pthread_cond_wait(&cv, &m_mut);
int id = *((int*) ptr);
std::cout << "thread " << id << '\n';
pthread_mutex_unlock(&m_mut);
pthread_exit(0);
return NULL;
}
condition is changed here!
void go() {
pthread_mutex_lock(&m_mut);
ready = true;
pthread_mutex_unlock(&m_mut);
pthread_cond_signal(&cv);
}
It can work if I change the last line of go() to pthread_cond_broadcast(&cv);
int main ()
{
pthread_t threads[10];
// spawn 10 threads:
for (int i=0; i<10; i++)
pthread_create(&threads[i], NULL, print_id, (void *) new int(i));
go();
for (int i=0; i<10; i++) pthread_join(threads[i], NULL);
pthread_mutex_destroy(&m_mut);
pthread_cond_destroy(&cv);
return 0;
}
The expected answer (arbitrary order) is
thread 0
....
thread 9
However, on my machine (ubuntu), it prints nothing.
Could anyone tell me the reason? Thanks.
From the manual page (with my emphasis):
pthread_cond_signal restarts one of the threads that are waiting on the condition variable cond. If no threads are waiting on cond, nothing happens. If several threads are waiting on cond, exactly one is restarted, but it is not specified which.
pthread_cond_broadcast restarts all the threads that are waiting on the condition variable cond. Nothing happens if no threads are waiting on cond.
Each of your ten threads is waiting on the same condition. You only call go() once - that's from main(). This calls pthread_cond_signal, which will only signal one of the threads (an arbitrary one). All the others will still be waiting, and hence the pthread_join hangs as they won't terminate. When you switch it to pthread_cond_broadcast, all of the threads are triggered.

How to debug deadlock in this small multithreaded program

I am new to multithreading and hence started with a small program. The job expected from the program is, to print integers one after the other by means of two threads in such a way that one thread should print one number and the other thread should print the next number and this process should continue till a maximum number defined.
For this I wrote a small program and iam facing dead lock. I tried to find mutex owner using gdb but it;s just printing $3 = 2 when I execute print mutex command.
Here is the source code:
#include <iostream>
#include <fstream>
#include <pthread.h>
#include <signal.h>
const int MAX_NUM = 13;
pthread_cond_t cond[1] = {PTHREAD_COND_INITIALIZER,};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int Count = 0;
using namespace std;
void* thread1(void*)
{
do {
cout<<"inside thread 1 abt to acquire lock"<<endl;
// Increment counter in thread1
pthread_mutex_lock(&mutex);
cout<<"inside thread 1 blocked"<<endl;
pthread_cond_wait(&cond[0],&mutex);
cout<<"after pthread_cond_wait in thread1"<<endl;
pthread_cond_signal(&cond[1]);
if(Count < MAX_NUM)
{
Count++;
pthread_mutex_unlock(&mutex);
cout<<"Printing from thread 1"<<endl;
cout<<Count<<endl;
}
else
{
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
}while(1);
}
void* thread2(void*)
{
do{
cout<<"inside thread 2 abt to acquire lock"<<endl;
pthread_mutex_lock(&mutex);
cout<<"inside thread 2 blocked"<<endl;
pthread_cond_wait(&cond[1],&mutex);
// Increment counter in thread2
pthread_cond_signal(&cond[0]);
if(Count < MAX_NUM)
{
Count++;
pthread_mutex_unlock(&mutex);
cout<<"Printing from thread 2"<<endl;
cout<<Count<<endl;
}
else
{
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
}while(1);
}
int main()
{
pthread_t t[2];
void* (*fun[2])(void*);
fun[0]=thread1;
fun[1]=thread2;
for (int i =0 ; i < 2; ++i)
{
pthread_create(&t[i],NULL,fun[i],NULL);
}
cout<<"threads created"<<endl;
pthread_cond_signal(&cond[0]);
cout<<"In main after sending signal"<<endl;
pthread_join(t[0],NULL);
pthread_join(t[1],NULL);
pthread_exit(NULL);
}
Output is:
inside thread 1 abt to acquire lock
inside thread 1 blocked
inside thread 2 abt to acquire lock
inside thread 2 blocked
threads created
In main after sending signal
I expected main() thread to send a signal to thread 1 which does it's job (i.e. updating counter) and then passes signal to thread 2 which does it's job (i.e. updating counter) and passes signal to thread 1. This process should continue until max number is reached. If max number is reached each process unlocks mutex and exits gracefully.
Please help me. I really tried a lot nothing worked.
the line
pthread_cond_t cond[1] = {PTHREAD_COND_INITIALIZER,};
defines an array of size 1, but later on you use cond[1], the second entry in the array, which is undefined. Did you mean
pthread_cond_t cond[2] = {PTHREAD_COND_INITIALIZER,PTHREAD_COND_INITIALIZER};
This looks like an unlucky typo. (Due to the preceeding MAX_NUM = 13?)
In addition to #TooTone's observation you need to understand one aspect of how condition variables work. If you signal a condition variable when no thread is blocked on it nothing will happen. The condition variable has no memory, so if a little bit later a thread blocks on in it will stay locked until the condition is signaled again.
Your main function signals cond[0] right after it started the threads, so it is possible that the threads haven't reached their blocking point yet. Or if they are blocked then it can happen that when one thread signals the other one that other one isn't blocked. So after you fix your condition variable array you will see that the test runs a bit more, but eventually deadlocks again.
I was able to make it work using a quick & dirty trick of introducing delays before signaling the condition variables. This gives the threads time to reach their blocking points before the signaling happens. Here is the modified code:
const int MAX_NUM = 13;
pthread_cond_t cond[2] = {PTHREAD_COND_INITIALIZER,PTHREAD_COND_INITIALIZER};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int Count = 0;
using namespace std;
void* thread1(void*)
{
do {
cout<<"inside thread 1 abt to acquire lock"<<endl;
// Increment counter in thread1
pthread_mutex_lock(&mutex);
cout<<"inside thread 1 blocked"<<endl;
pthread_cond_wait(&cond[0],&mutex);
cout<<"after pthread_cond_wait in thread1"<<endl;
if(Count < MAX_NUM)
{
Count++;
pthread_mutex_unlock(&mutex);
cout<<"Printing from thread 1"<<endl;
cout<<Count<<endl;
usleep(1000000);
pthread_cond_signal(&cond[1]);
}
else
{
pthread_mutex_unlock(&mutex);
usleep(1000000);
pthread_cond_signal(&cond[1]);
pthread_exit(NULL);
}
}while(1);
}
void* thread2(void*)
{
do{
cout<<"inside thread 2 abt to acquire lock"<<endl;
pthread_mutex_lock(&mutex);
cout<<"inside thread 2 blocked"<<endl;
pthread_cond_wait(&cond[1],&mutex);
// Increment counter in thread2
if(Count < MAX_NUM)
{
Count++;
pthread_mutex_unlock(&mutex);
cout<<"Printing from thread 2"<<endl;
cout<<Count<<endl;
usleep(1000000);
pthread_cond_signal(&cond[0]);
}
else
{
pthread_mutex_unlock(&mutex);
usleep(1000000);
pthread_cond_signal(&cond[0]);
pthread_exit(NULL);
}
}while(1);
}
int main()
{
pthread_t t[2];
void* (*fun[2])(void*);
fun[0]=thread1;
fun[1]=thread2;
for (int i =0 ; i < 2; ++i)
{
pthread_create(&t[i],NULL,fun[i],NULL);
}
cout<<"threads created"<<endl;
usleep(1000000);
pthread_cond_signal(&cond[0]);
cout<<"In main after sending signal"<<endl;
pthread_join(t[0],NULL);
pthread_join(t[1],NULL);
pthread_exit(NULL);
}
Using condition variables for this kind of thing isn't the best idea. Semaphores are better suited to the task because those do have memory and remember their signaled state even if nobody is waiting on them when they are signaled.

producer & consumer - multithreading

I wrote a multithreading program like this,
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
using namespace std;
pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t ec = PTHREAD_COND_INITIALIZER;
pthread_cond_t fc = PTHREAD_COND_INITIALIZER;
queue<int> qu;
const int N = 2;
void *producer(void *arg)
{
while(1) {
pthread_mutex_lock(&mu);
int tmp = rand();
qu.push(tmp);
pthread_cond_signal(&ec);
if ((int) qu.size() > N) {
pthread_cond_wait(&fc, &mu);
}
pthread_mutex_unlock(&mu);
}
}
void *consumer(void *arg)
{
while(1) {
pthread_mutex_lock(&mu);
if ((int) qu.size() < 1) {
pthread_cond_wait(&ec, &mu);
}
int tmp = qu.front();
qu.pop();
if ((int) qu.size() <= N) {
pthread_cond_signal(&fc);
}
pthread_mutex_unlock(&mu);
//sleep(1);
}
}
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, producer, NULL);
for (int i = 0; i < N; i++) {
pthread_t tid;
pthread_create(&tid, NULL, consumer, NULL);
}
printf("all created\n");
sleep(600);
}
When the qu.size() is geater than N, producer should stop producing, and when it's less than N, producer resumes producing.
The weired problem is, if I remove the sleep(1); in consumer, the program will run into segmentation fault, if I keep sleep(1);, the program runs ok.
Why? Does it mean the consumer consumes too fast?
Spurious wakeup might be the reason. Your thread will proceed if the condition is true, but if your thread proceeds you can't assume the condition is true.
Spurious wakeups from the pthread_cond_timedwait() or pthread_cond_wait() functions may occur. Since the return from pthread_cond_timedwait() or pthread_cond_wait() does not imply anything about the value of this predicate, the predicate should be re-evaluated upon such return.
So for example
if (qu.size() == 0) {
pthread_cond_wait(&ec, &mu);
}
should become
while (qu.size() == 0) {
pthread_cond_wait(&ec, &mu);
}
If you keep the sleep(1) call and the whole thing does not crash you're just lucky :)
Try initializing the mutex explicitly using the pthread_mutex_init() otherwise your pthread_mutex_lock() calls seem to fail.
From the docs:
Errors
The pthread_mutex_lock() and pthread_mutex_trylock()
functions may fail if:
EINVAL: The value specified by mutex
does not refer to an initialized mutex object.