Confusion with posix threads in cpp - c++

I'm really confused with this particular code. AFAIK, this program should not have a race condition but it does. What is really confusing is removing the loops and just duplicating the code works fine.
NOTE: I saw a question about threads in a loop but it does not really capture what i'm trying to impose.
Here it is
#include <cstdio>
#include <cstdlib>
#include <pthread.h>
void *functionC(void*);
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;
int main() {
pthread_t thread1, thread2;
pthread_t threads[] = { thread1, thread2 };
for (auto th : threads) {
if (pthread_create(&th, NULL, &functionC, NULL) != 0)
{
printf("Thread Creation Failed");
}
}
for (auto th : threads) {
pthread_join(th, NULL);
}
exit(0);
}
void *functionC(void *) {
pthread_mutex_lock(&mutex1);
counter++;
printf("Counter Value: %d\n", counter);
pthread_mutex_unlock(&mutex1);
return NULL;
}
Built as follows
FILE=mutex
all:
g++ $(FILE).cpp -lpthread -o bin && ./bin
I was expecting the counter variable to increment once per thread but sometimes nothing prints other times the counter variable remains 1 for both executions which i have read is due to low level scheduling operations.

Your bug is here (two places, the first of which is critical):
for (auto th : threads) {
That should be:
for (auto& th : threads) {
It needs to be a reference so that when you take the address of th and pass it to pthread_create(), you are actually passing the address of threads[0] and not merely the address of th.
Also note that thread1 and thread2 are useless in your program, and should be removed. Enabling compiler warnings would tell you this.

Related

two threads entering the critical section on the mutex

The following simplified example of several
I'm writing a c++20 software which explits pthreads. The simplified example shows how I have a shared resource shared_resource, an int variable, which is written by several threads, several times. To access the variable I use a mutex and a condition variable. A typical use of mutex and condition variables.
the num_readers is used as following:
greater than 0: multiple readers accessing the shared variable
0: neither writers nor readers are accessing the resource
-1: a writer is writing a new value on the resource. No more readers nor writers are avaibale until the writer releases the resource
The simplified version has no readers for focusing on the problem. Since num_readers = num_readers - 1; can be executed only when a writer releases the resource by setting it to 0 and signaling the other writers, I expect 0 or -1 values, but never -2!
The problem is that by executing the following I randomly get -2 values, so some interleaving problem is occurring I guess:
WAT>? num_readers -2
Process finished with exit code 1
#include <iostream>
#include <pthread.h>
#include <cstdlib>
#include <thread>
#include <random>
void* writer(void* parameters);
pthread_mutex_t mutex{PTHREAD_MUTEX_DEFAULT};
pthread_cond_t cond_writer = PTHREAD_COND_INITIALIZER;
int num_readers{0};
int shared_resource{0};
int main() {
const int WRITERS{500};
pthread_t writers[WRITERS];
for(unsigned int i=0; i < WRITERS; i++) {
pthread_create(&writers[i], NULL, writer, NULL);
}
for(auto &writer_thread : writers) {
pthread_join(writer_thread, NULL);
std::cout << "[main] writer returned\n";
}
std::cout << "[main] exiting..." << std::endl;
return 0;
}
void* writer(void* parameters) {
for (int i=0; i<5; i++) {
pthread_mutex_lock(&mutex);
while(num_readers != 0) {
if (num_readers < -1) {
std::cout << "WAT>? num_readers " << std::to_string(num_readers) << "\n";
exit(1);
}
pthread_cond_wait(&cond_writer, &mutex);
}
num_readers = num_readers - 1;
pthread_mutex_unlock(&mutex);
std::uniform_int_distribution<int> dist(1, 1000);
std::random_device rd;
int new_value = dist(rd);
shared_resource = new_value;
pthread_mutex_lock(&mutex);
num_readers = 0;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond_writer);
}
return 0;
}
So: why isn't this code thread safe?
Some issues stand out in your code:
You modify the number of readers in the write funtion. Only the reader function should do that.
Same thing for the signaling of the condition variable. That should only be signaled from the reader function.
incrementing and decrementing the number of readers is usually done with a semaphore: an atomic int and an associated condition variable.
Here is the algorithm:
int reader()
{
// indicate that a read is in progress.
//
// a. lock()/
// b. increment number of readers.
// c. unlock() as soon as possible, so other readers can also read reading.
//
// note that any write in progress will stop the thread here.
pthread_mutex_lock(&mutex);
++num_readers;
pthread_mutex_unlock(&mutex);
// read protected data
int result = shared_resource;
// decremennt readers count.
//
// note that calls to lock()/unlock() are not necessary if
// num_readers is atomic (I.e.: std::atomic<int>)
pthread_mutex_lock(&mutex);
if (--num_readers == 0)
pthread_cond_signal(&cond_writer); // last reader sets the cond_var
pthread_mutex_unlock(&mutex);
return result;
}
void writer(int value)
{
// lock
pthread_mutex_lock(&mutex);
// wait for no readers, the mutex is released while waiting for
// the last read to complete. Note that access to num_readers is
// done while the mutex is owned.
while (num_readers != 0)
pthread_cond_wait(&cond_writer, &mutex);
// modify protected data.
shared_resource = value;
// unlock.
pthread_mutex_unlock(&mutex);
}

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;
}

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.

Issue with pthreads_cond_wait and queue'ing pthreads

I'm trying to have pthreads run multiple instances of a function at once, to increase runtime speed and efficiency. My code is supposed to spawn threads and keep them open for whenever there is more items in the queue. Then those threads are supposed to do 'something'. The code is supposed to ask to "continue?" when there are no more items in the queue, and if I type "yes", then items should be added to the queue and the threads should continue doing 'something'. This is what I have so far,
# include <iostream>
# include <string>
# include <pthread.h>
# include <queue>
using namespace std;
# define NUM_THREADS 100
int main ( );
queue<int> testQueue;
void *checkEmpty(void* arg);
void *playQueue(void* arg);
void matrix_exponential_test01 ( );
void matrix_exponential_test02 ( );
pthread_mutex_t queueLock;
pthread_cond_t queue_cv;
int main()
{
pthread_t threads[NUM_THREADS+1];
pthread_mutex_init(&queueLock, NULL);
pthread_cond_init (&queue_cv, NULL);
for( int i=0; i < NUM_THREADS; i++ )
{
pthread_create(&threads[i], NULL, playQueue, (void*)NULL);
}
string cont = "yes";
do
{
cout<<"Continue? ";
getline(cin, cont);
pthread_mutex_lock (&queueLock);
for(int z=0; z<10; z++)
{
testQueue.push(1);
}
pthread_mutex_unlock (&queueLock);
}while(cont.compare("yes"));
pthread_mutex_destroy(&queueLock);
pthread_cond_destroy(&queue_cv);
pthread_exit(NULL);
return 0;
}
void* checkEmpty(void* arg)
{
while(true)
{
pthread_mutex_lock (&queueLock);
if(!testQueue.empty()){
pthread_cond_signal(&queue_cv);}
pthread_mutex_unlock (&queueLock);
}
pthread_exit(NULL);
}
void* playQueue(void* arg)
{
while(true)
{
pthread_cond_wait(&queue_cv, &queueLock);
pthread_mutex_lock (&queueLock);
if(!testQueue.empty())
{
testQueue.pop();
cout<<testQueue.size()<<endl;
}
pthread_mutex_unlock (&queueLock);
}
pthread_exit(NULL);
}
So my issue lies with the fact that the code goes into deadlock, and I cant figure out where the issue occurs. I'm no veteran with multithreading so its very easy for me to make a mistake here. I am also running this on Windows.
You have two issues :
The condition variable queue_cv is never signaled. You can signal it with pthread_cond_signal after having pushed elements in the queue : pthread_cond_signal(&queue_cv);
In playQueue, you try to acquire the lock after returning from pthread_cond_wait : since your mutex is not reentrant, this is undefined behavior (this is likely the source of your deadlock). Just remove the pthread_mutex_lock (&queueLock);
Note:
I'm not sure what is it's true purpose, but the checkEmpty() method is never called

Thread interruption from another thread

I'm creating 9 threads using something like this (all threads will process infinity loop)
void printStr();
thread func_thread(printStr);
void printStr() {
while (true) {
cout << "1\n";
this_thread::sleep_for(chrono::seconds(1));
}
}
I also create 10th thread to control them. How would I stop or kill any of this 9 threads from my 10th? Or suggest another mechanism please.
You can use, for example, atomic boolean:
#include <thread>
#include <iostream>
#include <vector>
#include <atomic>
using namespace std;
std::atomic<bool> run(true);
void foo()
{
while(run.load(memory_order_relaxed))
{
cout << "foo" << endl;
this_thread::sleep_for(chrono::seconds(1));
}
}
int main()
{
vector<thread> v;
for(int i = 0; i < 9; ++i)
v.push_back(std::thread(foo));
run.store(false, memory_order_relaxed);
for(auto& th : v)
th.join();
return 0;
}
EDIT (in response of your comment): you can also use a mutual variable, protected by a mutex.
#include <thread>
#include <iostream>
#include <vector>
#include <mutex>
using namespace std;
void foo(mutex& m, bool& b)
{
while(1)
{
cout << "foo" << endl;
this_thread::sleep_for(chrono::seconds(1));
lock_guard<mutex> l(m);
if(!b)
break;
}
}
void bar(mutex& m, bool& b)
{
lock_guard<mutex> l(m);
b = false;
}
int main()
{
vector<thread> v;
bool b = true;
mutex m;
for(int i = 0; i < 9; ++i)
v.push_back(thread(foo, ref(m), ref(b)));
v.push_back(thread(bar, ref(m), ref(b)));
for(auto& th : v)
th.join();
return 0;
}
It is never appropriate to kill a thread directly, you should instead send a signal to the thread to tell it to stop by itself. This will allow it to clean up and finish properly.
The mechanism you use is up to you and depends on the situation. It can be an event or a state checked periodically from within the thread.
std::thread objects are non - interruptible. You will have to use another thread library like boost or pthreads to accomplish your task. Please do note that killing threads is dangerous operation.
To illustrate how to approach this problem in pthread using cond_wait and cond_signal,In the main section you could create another thread called monitor thread that will keep waiting on a signal from one of the 9 thread.
pthread_mutex_t monMutex;////mutex
pthread_cond_t condMon;////condition variable
Creating threads:
pthread_t *threads = (pthread_t*) malloc (9* sizeof(pthread_t));
for (int t=0; t < 9;t++)
{
argPtr[t].threadId=t;
KillAll=false;
rc = pthread_create(&threads[t], NULL, &(launchInThread), (void *)&argPtr[t]);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
creating monitor thread:
monitorThreadarg.threadArray=threads;//pass reference of thread array to monitor thread
monitorThreadarg.count=9;
pthread_t monitor_thread;
rc= pthread_create(&monitor_thread,NULL,&monitorHadle,(void * )(&monitorThreadArg));
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
then wait on 9 threads and monitor thread:
for (s=0; s < 9;s++)
{
pthread_join(threads[s], &status);
}
pthread_cond_signal(&condMon);// if all threads finished successfully then signal monitor thread too
pthread_join(monitor_thread, &status);
cout << "joined with monitor thread"<<endl;
The monitor function would be something like this:
void* monitorHadle(void* threadArray)
{
pthread_t* temp =static_cast<monitorThreadArg*> (threadArray)->threadArray;
int number =static_cast<monitorThreadArg*> (threadArray)->count;
pthread_mutex_lock(&monMutex);
mFlag=1;//check so that monitor threads has initialised
pthread_cond_wait(&condMon,&monMutex);// wait for signal
pthread_mutex_unlock(&monMutex);
void * status;
if (KillAll==true)
{
printf("kill all \n");
for (int i=0;i<number;i++)
{
pthread_cancel(temp[i]);
}
}
}
the function what will be launched over 9 threads should be something like this:
void launchInThread( void *data)
{
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
while(1)
{
try
{
throw("exception whenever your criteria is met");
}
catch (string x)
{
cout << "exception form !! "<< pthread_self() <<endl;
KillAll=true;
while(!mFlag);//wait till monitor thread has initialised
pthread_mutex_lock(&monMutex);
pthread_cond_signal(&condMon);//signail monitor thread
pthread_mutex_unlock(&monMutex);
pthread_exit((void*) 0);
}
}
}
Please note that if you dont't put :
thread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
after launching your thread then your threads wouldn't terminate on thread_cancel call.
It is necessary that you clean up up all the data before you cancel a thread.