providing critical section for threads in c++ - c++

In this c++ program , I have created 10 threads which race to each other to acquire critical section.For this mean I'm using conditional variable as below code.The dispatcher in this program will grant one thread at a time to enter critical section.But there is a subtle problem. when dispatcher grant to a thread to enter , it will set ready_pipe variable true. If one new thread comes at this time (before consumer set ready_pipe=flase) newcomer thread will across the critical section without permission.
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
std::condition_variable con_var_pipe;
bool ready_pipe = false;
std::mutex pipe_mutex;
bool critical_section_is_free=true;
void dispatcher()
{
while(true)
{
if(critical_section_is_free)
{
critical_section_is_free=false;
// send signal to a thread to enter critical section
std::lock_guard<std::mutex> lk(pipe_mutex);
ready_pipe = true;
con_var_pipe.notify_one();
}
}
}
void consumer()
{
std::unique_lock<std::mutex> lk(pipe_mutex);
/* The Problem is Here at below line.When a new thread comes,
it will pass through this block because it see ready_pipe is true!!!*/
con_var_pipe.wait(lk, [] {return ready_pipe;});
/// critical section starts
ready_pipe=false;
/// here accessing pipe is occurring .
/// critical section ends
critical_section_is_free=true;
}
int main()
{
std::thread allThreads[10];
for(int i = 0 ; i<10 ; i++)
{
allThreads[i]=std::thread(consumer);
}
thread disp(dispatcher);
for(int i = 0 ; i< 6 ; i++)
{
allThreads[i].join();
}
disp.join();
return 0;
}
Further more , this code is also deficient because of a while(true) statement in dispatcher function and make busy waiting.
So the questions are :
1-how to create mutual exclusion when new thread comes.
2-how to avoid busy waiting in dispatcher() function.
3-and how threads be served in order as they come and register in wait().

Just use two counters and a boolean to implement a basic "take a number" scheme.
One counter, released_thread, indicates which thread may proceed. This is logically equivalent to the "now serving" indicator.
The other, next_waiter, indicates which thread waits next. This is logically equivalent to the next number that will be taken
A boolean indicates whether the thread is permitted to proceed and when it is finished, so the executive knows when to call the next number.
The algorithms are as follows:
To wait:
Acquire the lock.
Note the value of the next_waiter variable and increment it.
Broadcast (notify all) the condition variable.
Wait on the condition variable until the boolean is true and the released_thread counter is equal to the value noted in step 2.
Release the lock.
When finished, acquire the lock, set the boolean to false, broadcast the condition variable, and release the lock.
Executive:
Acquire the lock.
Wait on the condition variable until the boolean is false and next_waiter is not equal to released_thread.
Increment released_thread and set the boolean to true.
Broadcast the condition variable.
Go to step 2.

Related

Why the program get deadlocked if I comment the "while" block? How does the "yield" line in it effect? [duplicate]

This question already has answers here:
condition variable - why calling pthread_cond_signal() before calling pthread_cond_wait() is a logical error?
(5 answers)
Closed 5 years ago.
I'm learning condition_variable and running some examples. I'm curious that why the following code get deadlock if I comment the block. It's a simple consumer and producer example using condition_variable. I think it's a deadlock problem, isn't it?
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
mutex mtx;
condition_variable cv;
int cargo = 0;
bool shipment_available()
{
return cargo != 0;
}
void consume(int cnt)
{
for (int i = 0; i < cnt; i++)
{
unique_lock<mutex> lck(mtx);
cv.wait(lck, shipment_available);
printf("%d\n", cargo);
cargo = 0;
}
}
int main()
{
thread consumer_thread(consume, 10);
for (int i = 0; i < 10; i++)
{
//while (shipment_available()) // Dead lock without this block
//{
// std::this_thread::yield();
//}
unique_lock<mutex> lck(mtx);
cargo = i + 1;
cv.notify_one();
}
consumer_thread.join();
}
It runs well if I uncomment the block.
So walk through this highly likely possibility:
main() starts up the consumer thread.
Before the thread can acquire the mutex, main() locks it, increments cargo, and fires the notification, then releases the mutex by scope-rotation ten times.
main() now runs down to join the consumer thread.
Consumer finally acquires the mutex, and prepares to wait on the condition variable for the given predicate (non-zero cargo).
The predicate is already true, so no wait is performed.
The consumer zeros the cargo, then releases the mutex by scope-rotation.
The consumer loops for the second time, locks the mutex, then checks the predicate, only now the predicate is false because cargo is indeed zero, so it waits on the condition variable (releasing the mutex in the process) for a signal that will never come. The only thing that ever sent that signal is main(), and it is just camped out waiting for the consumer thread to join up, which can now never happen.
In short, you seem to be of the belief that condition variables signals stack up. That simply isn't the case. if no one is actively waiting on a notification at the time it is posted, it is simply lost to the ether.
Finally, and this is important, your "fix" is completely wrong in itself. The shipment_available function examines predicate data (i.e. data that must be protected by the mutex enshrouding it, not only for modification, but likewise for examination). Checking that without the mutex locked in main is a recipe for a race condition.
My suggestion is to reduce cargo by one rather than zeroing it out. Alternatively you could increment i by the value of cargo before zeroing it, thereby hastening i's ascent to the cnt limit, but you appear to be using an ascending cargo amount, so you'll have to make other adjustments accordingly.

C++ Holding a number of threads

I'm new to C++ (on Windows) and threading and I'm currently trying to find a solution to my problem using mutexes, semaphores and events.
I'm trying to create a Barrier class with a constructor and a method called Enter. The class Barrier with it's only method Enter is supposed to hold off any thread that enters it, until a number of thread have reached that method. The number of thread to wait for it recieved at the contructor.
My problem is how do I use the locks to create that effect? what I need is something like a reversed semaphore, that holds threads until a count has been reached and not like the regular semaphore works that lets threads in until a count is reached.
Any ideas as to how to go about this would be great.
Thanks,
Netanel.
Maybe:
In the ctor, store the limit count and create an empty semaphore.
When a thread calls Enter, lock a mutex first so you can twiddle inside safely. Inc a thread count toward the limit count. If the limit has not yet been reached, release the mutex and wait on the semaphore. If the limit is reached, signal the semaphore[limit-1] times in a loop, zero the thread count, (ready for next time), release the mutex and return from Enter(). Any threads that were waiting on the semaphore, and are now ready/running, should just return from their 'Enter' call.
The mutex prevents any released thread that loops around from 'getting in again' until all the threads that called 'Enter' and waited have been set running and the barrier is reset.
You can implement it with condition variable.
Here is an example:
I declare 25 threads and launch them doing the WorkerThread function.
The condition I am checking to block/unblick the threads is whether the number of threads in the section is less than 2.
(I have added some asserts to prove what my coode does).
My code is simply sleeping in the critical section and after I decrease the number of threads in the critical section.
I also added a mutex for the cout to have clean messages.
#include
#include
#include
#include
#include
#include
#include /* assert */
using namespace std;
std::mutex m;
atomic<int> NumThreadsInCritialSection=0;
int MaxNumberThreadsInSection=2;
std::condition_variable cv;
mutex coutMutex;
int WorkerThread()
{
// Wait until main() sends data
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return NumThreadsInCritialSection<MaxNumberThreadsInSection;});
}
assert (NumThreadsInCritialSection<MaxNumberThreadsInSection);
assert (NumThreadsInCritialSection>=0);
NumThreadsInCritialSection++;
{
std::unique_lock<std::mutex> lk(coutMutex);
cout<<"NumThreadsInCritialSection= "<<NumThreadsInCritialSection<<endl;
}
std::this_thread::sleep_for(std::chrono::seconds(5));
NumThreadsInCritialSection--;
{
std::unique_lock<std::mutex> lk(coutMutex);
cout<<"NumThreadsInCritialSection= "<<NumThreadsInCritialSection<<endl;
}
cv.notify_one();
return 0;
}
int main()
{
vector<thread> vWorkers;
for (int i=0;i<25;++i)
{
vWorkers.push_back(thread(WorkerThread));
}
for (auto j=vWorkers.begin(); j!=vWorkers.end(); ++j)
{
j->join();
}
return 0;
}
Hope that helps, tell me if you have any questions, I can comment or change my code.
Pseudocode outline might look like this:
void Enter()
{
Increment counter (atomically or with mutex)
if(counter >= desired_count)
{
condition_met = true; (protected if bool writes aren't atomic on your architecture)
cond_broadcast(blocking_cond_var);
}
else
{
Do a normal cond_wait loop-plus-predicate-check (waiting for the broadcast and checking condition_met each iteration to protect for spurious wakeups).
}
}

(C++ Threads): Creating worker threads that will be listening to jobs and executing them concurrently when wanted

Suppose we have two workers. Each worker has an id of 0 and 1. Also suppose that we have jobs arriving all the time, each job has also an identifier 0 or 1 which specifies which worker will have to do this job.
I would like to create 2 threads that are initially locked, and then when two jobs arrive, unlock them, each of them does their job and then lock them again until other jobs arrive.
I have the following code:
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
struct job{
thread jobThread;
mutex jobMutex;
};
job jobs[2];
void executeJob(int worker){
while(true){
jobs[worker].jobMutex.lock();
//do some job
}
}
void initialize(){
int i;
for(i=0;i<2;i++){
jobs[i].jobThread = thread(executeJob, i);
}
}
int main(void){
//initialization
initialize();
int buffer[2];
int bufferSize = 0;
while(true){
//jobs arrive here constantly,
//once the buffer becomes full,
//we unlock the threads(workers) and they start working
bufferSize = 2;
if(bufferSize == 2){
for(int i = 0; i<2; i++){
jobs[i].jobMutex.unlock();
}
}
break;
}
}
I started using std::thread a few days ago and I'm not sure why but Visual Studio gives me an error saying abort() has been called. I believe there's something missing however due to my ignorance I can't figure out what.
I would expect this piece of code to actually
Initialize the two threads and then lock them
Inside the main function unlock the two threads, the two threads will do their job(in this case nothing) and then they will become locked again.
But it gives me an error instead. What am I doing wrong?
Thank you in advance!
For this purpose you can use boost's threadpool class.
It's efficient and well tested. opensource library instead of you writing newly and stabilizing it.
http://threadpool.sourceforge.net/
main()
{
pool tp(2); //number of worker threads-currently its 2.
// Add some tasks to the pool.
tp.schedule(&first_task);
tp.schedule(&second_task);
}
void first_task()
{
...
}
void second_task()
{
...
}
Note:
Suggestion for your example:
You don't need to have individual mutex object for each thread. Single mutex object lock itself will does the synchronization between all the threads. You are locking mutex of one thread in executejob function and without unlocking another thread is calling lock with different mutex object leading to deadlock or undefined behaviour.
Also since you are calling mutex.lock() inside whileloop without unlocking , same thread is trying to lock itself with same mutex object infinately leading to undefined behaviour.
If you donot need to execute threads parallel you can have one global mutex object can be used inside executejob function to lock and unlock.
mutex m;
void executeJob(int worker)
{
m.lock();
//do some job
m.unlock();
}
If you want to execute job parallel use boost threadpool as I suggested earlier.
In general you can write an algorithm similar to the following. It works with pthreads. I'm sure it would work with c++ threads as well.
create threads and make them wait on a condition variable, e.g. work_exists.
When work arrives you notify all threads that are waiting on that condition variable. Then in the main thread you start waiting on another condition variable work_done
Upon receiving work_exists notification, worker threads wake up, and grab their assigned work from jobs[worker], they execute it, they send a notification on work_done variable, and then go back to waiting on the work_exists condition variable
When main thread receives work_done notification it checks if all threads are done. If not, it keeps waiting till the notification from last-finishing thread arrives.
From cppreference's page on std::mutex::unlock:
The mutex must be unlocked by all threads that have successfully locked it before being destroyed. Otherwise, the behavior is undefined.
Your approach of having one thread unlock a mutex on behalf of another thread is incorrect.
The behavior you're attempting would normally be done using std::condition_variable. There are examples if you look at the links to the member functions.

Two Condition Variables and avoiding deadlock

I have two condition variables:
CondVar1
CondVar2
Used in two threads like this (pseudo-code):
// thread1 starts in 'waiting' mode, and then Thread2 signals
void Thread1()
{
CondVar1->Wait();
CondVar2->Signal();
}
void Thread2()
{
CondVar1->Signal();
CondVar2->Wait();
}
Can this cause a deadlock? meaning, thread1 waits, thread2 signals, and then can thread1 signals before thread2 enters Wait(), meaning thread2 will never return?
Thanks
You don't usually just wait on a condition variable. The common use pattern is holding a lock, checking a variable that determines whether you can proceed or not and if you cannot wait in the condition:
// pseudocode
void push( T data ) {
Guard<Mutex> lock( m_mutex ); // Hold a lock on the queue
while (m_queue.full()) // [1]
m_cond1.wait(lock); // Wait until a consumer leaves a slot for me to write
// insert data
m_cond2.signal_one(); // Signal consumers that might be waiting on an empty queue
}
Some things to note: most libraries allow for spurious wakes in condition variables. While it is possible to implement a condition variable that avoid spurious wakes, the cost of the operations would be higher, so it is considered a lesser evil to require users to recheck the state before continuing (while loop in [1]).
Some libraries, notably C++11, allow you to pass a predicate, and will implement the loop internally: cond.wait(lock, [&queue](){ return !queue.full(); } );
There are two situations that could lead to a deadlock here:
In normal execution, the one you described. It is possible that the variable is signaled before the thread reaches the call to Wait, so the signal is lost.
A spurious wake-up could happen, causing the first thread to leave the call to Wait before actually being signaled, hence signaling Thread 2 who is not yet waiting.
You should design your code as follows when using signaling mechanisms:
bool thread1Waits = true;
bool thread2Waits = true;
void Thread1()
{
while(thread1Waits) CondVar1->Wait();
thread2Waits = false;
CondVar2->Signal();
}
void Thread2()
{
thread1Waits = false;
CondVar1->Signal();
while(thread2Waits) CondVar2->Wait();
}
Of course, this assumes there are locks protecting the condition variables and that additionally thread 1 runs before thread 2.

C++ multithreading, simple consumer / producer threads, LIFO, notification, counter

I am new to multi-thread programming, I want to implement the following functionality.
There are 2 threads, producer and consumer.
Consumer only processes the latest value, i.e., last in first out (LIFO).
Producer sometimes generates new value at a faster rate than consumer can
process. For example, producer may generate 2 new value in 1
milli-second, but it approximately takes consumer 5 milli-seconds to process.
If consumer receives a new value in the middle of processing an old
value, there is no need to interrupt. In other words, consumer will finish current
execution first, then start an execution on the latest value.
Here is my design process, please correct me if I am wrong.
There is no need for a queue, since only the latest value is
processed by consumer.
Is notification sent from producer being queued automatically???
I will use a counter instead.
ConsumerThread() check the counter at the end, to make sure producer
doesn't generate new value.
But what happen if producer generates a new value just before consumer
goes to sleep(), but after check the counter???
Here is some pseudo code.
boost::mutex mutex;
double x;
void ProducerThread()
{
{
boost::scoped_lock lock(mutex);
x = rand();
counter++;
}
notify(); // wake up consumer thread
}
void ConsumerThread()
{
counter = 0; // reset counter, only process the latest value
... do something which takes 5 milli-seconds ...
if (counter > 0)
{
... execute this function again, not too sure how to implement this ...
}
else
{
... what happen if producer generates a new value here??? ...
sleep();
}
}
Thanks.
If I understood your question correctly, for your particular application, the consumer only needs to process the latest available value provided by the producer. In other words, it's acceptable for values to get dropped because the consumer cannot keep up with the producer.
If that's the case, then I agree that you can get away without a queue and use a counter. However, the shared counter and value variables will be need to be accessed atomically.
You can use boost::condition_variable to signal notifications to the consumer that a new value is ready. Here is a complete example; I'll let the comments do the explaining.
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/locks.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
boost::mutex mutex;
boost::condition_variable condvar;
typedef boost::unique_lock<boost::mutex> LockType;
// Variables that are shared between producer and consumer.
double value = 0;
int count = 0;
void producer()
{
while (true)
{
{
// value and counter must both be updated atomically
// using a mutex lock
LockType lock(mutex);
value = std::rand();
++count;
// Notify the consumer that a new value is ready.
condvar.notify_one();
}
// Simulate exaggerated 2ms delay
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
}
}
void consumer()
{
// Local copies of 'count' and 'value' variables. We want to do the
// work using local copies so that they don't get clobbered by
// the producer when it updates.
int currentCount = 0;
double currentValue = 0;
while (true)
{
{
// Acquire the mutex before accessing 'count' and 'value' variables.
LockType lock(mutex); // mutex is locked while in this scope
while (count == currentCount)
{
// Wait for producer to signal that there is a new value.
// While we are waiting, Boost releases the mutex so that
// other threads may acquire it.
condvar.wait(lock);
}
// `lock` is automatically re-acquired when we come out of
// condvar.wait(lock). So it's safe to access the 'value'
// variable at this point.
currentValue = value; // Grab a copy of the latest value
// while we hold the lock.
}
// Now that we are out of the mutex lock scope, we work with our
// local copy of `value`. The producer can keep on clobbering the
// 'value' variable all it wants, but it won't affect us here
// because we are now using `currentValue`.
std::cout << "value = " << currentValue << "\n";
// Simulate exaggerated 5ms delay
boost::this_thread::sleep(boost::posix_time::milliseconds(500));
}
}
int main()
{
boost::thread c(&consumer);
boost::thread p(&producer);
c.join();
p.join();
}
ADDENDUM
I was thinking about this question recently, and realized that this solution, while it may work, is not optimal. Your producer is using all that CPU just to throw away half of the computed values.
I suggest that you reconsider your design and go with a bounded blocking queue between the producer and consumer. Such a queue should have the following characteristics:
Thread-safe
The queue has a fixed size (bounded)
If the consumer wants to pop the next item, but the queue is empty, the operation will be blocked until notified by the producer that an item is available.
The producer can check if there's room to push another item and block until the space becomes available.
With this type of queue, you can effectively throttle down the producer so that it doesn't outpace the consumer. It also ensures that the producer doesn't waste CPU resources computing values that will be thrown away.
Libraries such as TBB and PPL provide implementations of concurrent queues. If you want to attempt to roll your own using std::queue (or boost::circular_buffer) and boost::condition_variable, check out this blogger's example.
The short answer is that you're almost certainly wrong.
With a producer/consumer, you pretty much need a queue between the two threads. There are basically two alternatives: either your code won't will simply lose tasks (which usually equals not working at all) or else your producer thread will need to block for the consumer thread to be idle before it can produce an item -- which effectively translates to single threading.
For the moment, I'm going to assume that the value you get back from rand is supposed to represent the task to be executed (i.e., is the value produced by the producer and consumed by the consumer). In that case, I'd write the code something like this:
void producer() {
for (int i=0; i<100; i++)
queue.insert(random()); // queue.insert blocks if queue is full
queue.insert(-1.0); // Tell consumer to exit
}
void consumer() {
double value;
while ((value = queue.get()) != -1) // queue.get blocks if queue is empty
process(value);
}
This, relegates nearly all the interlocking to the queue. The rest of the code for both threads pretty much ignores threading issues entirely.
Implementing a pipeline is actually quite tricky if you are doing it ground-up. For example, you'd have to use condition variable to avoid the kind of race condition you described in your question, avoid busy waiting when implementing the mechanism for "waking up" the consumer etc... Even using a "queue" of just 1 element won't save you from some of these complexities.
It's usually much better to use specialized libraries that were developed and extensively tested specifically for this purpose. If you can live with Visual C++ specific solution, take a look at Parallel Patterns Library, and the concept of Pipelines.