Java Concurrent:An issue of producers and consumers - java.util.concurrent

The first is my understanding:
notify() only will wake one thread. The awakened thread will continue from wait().
public class T_SynList extends LinkedList<Item>{
public static int MAX=5;
public synchronized void produce(String producer)
{
while(size()==MAX)
{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
add(new Item(producer,0));
notify();
}
public synchronized Item consume(String consumer)
{
//**My doubt!!!!!!!!**
while(size()==0)
{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Item item=removeFirst();
item.setConsumer(consumer);
notify();
return item;
}
}
There are 1 producers and 5 consumers. If I change while(size()==0) to if(size()==0), the procedure will get error(removeFirst() from a list with size=0).
The reason may be wake up two consumer threads at the same time but only one can continue. But document said that notify() only wake one thread. Why can't I do such changes?

The while(size() == 0) is im portant. If the consumer is woken up, he checks for himself if there is a element to consume. If not, he goes back to sleep.
The notify() method will wake up ONE thread on the same monitor ('this' in your case). It's possible that the finished consumer wakes up another consumer after taking the last element.
If you use if(size()==0) the other consumer is woken up, tries to take an element and rises an error.
You have to also use a notfyAll() to wake up all threads, the fastest takes the element and all others will go back to sleep. If not, it's possible that you got stock in a deadlock.
p1 -> put element -> notify c1 -> sleep
c1 -> take element -> notify c2 -> sleep
c2 -> no element -> sleep -> not waking up anyone -> deadlock

Related

Correct way to wait a condition variable that is notified by several threads

I'm trying to do this with the C++11 concurrency support.
I have a sort of thread pool of worker threads that all do the same thing, where a master thread has an array of condition variables (one for each thread, they need to 'start' synchronized, ie not run ahead one cycle of their loop).
for (auto &worker_cond : cond_arr) {
worker_cond.notify_one();
}
then this thread has to wait for a notification of each thread of the pool to restart its cycle again. Whats the correct way of doing this? Have a single condition variable and wait on some integer each thread that isn't the master is going to increase? something like (still in the master thread)
unique_lock<std::mutex> lock(workers_mtx);
workers_finished.wait(lock, [&workers] { return workers = cond_arr.size(); });
I see two options here:
Option 1: join()
Basically instead of using a condition variable to start the calculations in your threads, you spawn a new thread for every iteration and use join() to wait for it to be finished. Then you spawn new threads for the next iteration and so on.
Option 2: locks
You don't want the main-thread to notify as long as one of the threads is still working. So each thread gets its own lock, which it locks before doing the calculations and unlocks afterwards. Your main-thread locks all of them before calling the notify() and unlocks them afterwards.
I see nothing fundamentally wrong with your solution.
Guard workers with workers_mtx and done.
We could abstract this with a counting semaphore.
struct counting_semaphore {
std::unique_ptr<std::mutex> m=std::make_unique<std::mutex>();
std::ptrdiff_t count = 0;
std::unique_ptr<std::condition_variable> cv=std::make_unique<std::condition_variable>();
counting_semaphore( std::ptrdiff_t c=0 ):count(c) {}
counting_semaphore(counting_semaphore&&)=default;
void take(std::size_t n = 1) {
std::unique_lock<std::mutex> lock(*m);
cv->wait(lock, [&]{ if (count-std::ptrdiff_t(n) < 0) return false; count-=n; return true; } );
}
void give(std::size_t n = 1) {
{
std::unique_lock<std::mutex> lock(*m);
count += n;
if (count <= 0) return;
}
cv->notify_all();
}
};
take takes count away, and blocks if there is not enough.
give adds to count, and notifies if there is a positive amount.
Now the worker threads ferry tokens between two semaphores.
std::vector< counting_semaphore > m_worker_start{count};
counting_semaphore m_worker_done{0}; // not count, zero
std::atomic<bool> m_shutdown = false;
// master controller:
for (each step) {
for (auto&& starts:m_worker_start)
starts.give();
m_worker_done.take(count);
}
// master shutdown:
m_shutdown = true;
// wake up forever:
for (auto&& starts:m_worker_start)
starts.give(std::size_t(-1)/2);
// worker thread:
while (true) {
master->m_worker_start[my_id].take();
if (master->m_shutdown) return;
// do work
master->m_worker_done.give();
}
or somesuch.
live example.

boost async_wait return handler never gets called

I am working with the boost::asio tcp, version 1.57, creating a custom server/client, roughly following this example: Async_Tcp_Client , but I'm running the io_service run() in it's own thread per server/client. Also, there can be multiple server/clients per application.
Following the example I put my await_output function to sleep when I DON'T want to send a Message, and waking it up when I do want to send one (via async_write). After a varying amount of send-operations (sometimes less then 10, sometimes several thousand) I run into strange behaviour of my await_output Deadline (a boost deadline timer).
At some point, the async_wait against the timer just "disappears" and doesn't return when I cancel the deadline to send a message.
The transmit function, that is called by the Application owning the Client/Server (only by the application though, I guess it is not very threadsafe);
The await_output function that is waiting on the mOutputQueueDeadline;
And the handle_write function:
void SocketTcp::transmit(std::string pMsg) {
if (mStopped)
{ return; }
mOutputQueue.push(pMsg); // a global queue
// Signal that the output queue contains messages. Modifying the expiry
// will wake the output actor, if it is waiting on the timer.
size_t quits = mOutputQueueDeadline.expires_at(boost::posix_time::neg_infin);
//this returns '0' when the error occurs
}
void SocketTcp::await_output(const boost::system::error_code& ec)
{
if (mStopped)
{ return; }
if (mOutputQueue.empty())
{
size_t quits = mOutputQueueDeadline.expires_at(boost::posix_time::pos_infin);
mOutputQueueDeadline.async_wait(boost::bind(&SocketTcp::await_output, this, _1));
//this async_wait starts a wait on the deadline, that sometimes never returns!
}
else
{
boost::asio::async_write(mSocket,
boost::asio::buffer(mOutputQueue.front()),
boost::bind(&SocketTcp::handle_write, this, _1));
}
}
void SocketTcp::handle_write(const boost::system::error_code& ec)
{
if (mStopped)
{ return; }
if(!ec)
{
mOutputQueue.pop(); //remove sent element from queue
boost::system::error_code errcode;
await_output(errcode); //start the waiting actor for outgoing messages
}
else
{
mConnected = false; //update the connection status
this->stop();
}
}
I tried implementing a workaround, restarting the await_output in transmit() when expire_at returns 0, but that leads to TWO actors beeing awakened the next time I send a message, and then running into a crash (String iterator not dereferencable - the design doesn't allow for parallel send OP, much less trying to send the same message...)
I tried debugging with the BOOST_ASIO_ENABLE_HANDLER_TRACKING option, and found the error here:
#asio|1468415460.456019|0|deadline_timer#000000000050AB88.cancel //transmit cancels the timer
#asio|1468415460.456019|>474|ec=system:995 //await_output is called
#asio|1468415460.456019|474*479|socket#000000000050A9D8.async_send //starts the async send
#asio|1468415460.457019|<474|
#asio|1468415460.457019|>479|ec=system:0,bytes_transferred=102 //async send returns to it's handler
#asio|1468415460.457019|479|deadline_timer#000000000050AB88.cancel
//this cancel op is the only difference to the 'normal' order,
//not sure where it originates though!!
#asio|1468415460.457019|479*480|deadline_timer#000000000050AB88.async_wait //the handler starts the new async wait
//handler 480 never gets called when the deadline is canceled the next time
#asio|1468415460.457019|<479|
I'm pretty new to c++ as well as the stackoverflow (even though it has already safed me multiple times!) so please tell me if I can improve my question somehow!

std::condition_variable not properly wakes up after std::condition_variable::notify_all() from other thread

This code is simplification of real project code. Main thread create worker thread and wait with std::condition_variable for worker thread really started. In code below std::condition_variable wakes up after current_thread_state becomes "ThreadState::Stopping" - this is the second notification from worker thread, that is the main thread did not wake up after the first notification, when current_thread_state becomes "ThreadState::Starting". The result was deadlock. Why this happens? Why std::condition_variable not wake up after first thread_event.notify_all()?
int main()
{
std::thread thread_var;
struct ThreadState {
enum Type { Stopped, Started, Stopping };
};
ThreadState::Type current_thread_state = ThreadState::Stopped;
std::mutex thread_mutex;
std::condition_variable thread_event;
while (true) {
{
std::unique_lock<std::mutex> lck(thread_mutex);
thread_var = std::move(std::thread([&]() {
{
std::unique_lock<std::mutex> lck(thread_mutex);
cout << "ThreadFunction() - step 1\n";
current_thread_state = ThreadState::Started;
}
thread_event.notify_all();
// This code need to disable output to console (simulate some work).
cout.setstate(std::ios::failbit);
cout << "ThreadFunction() - step 1 -> step 2\n";
cout.clear();
{
std::unique_lock<std::mutex> lck(thread_mutex);
cout << "ThreadFunction() - step 2\n";
current_thread_state = ThreadState::Stopping;
}
thread_event.notify_all();
}));
while (current_thread_state != ThreadState::Started) {
thread_event.wait(lck);
}
}
if (thread_var.joinable()) {
thread_var.join();
current_thread_state = ThreadState::Stopped;
}
}
return 0;
}
Once you call the notify_all method, your main thread and your worker thread (after doing its work) both try to get a lock on the thread_mutex mutex. If your work load is insignificant, like in your example, the worker thread is likely to get the lock before the main thread and sets the state back to ThreadState::Stopped before the main thread ever reads it. This results in a dead lock.
Try adding a significant work load, e.g.
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
to the worker thread. Dead locks are far less likely now. Of course, this is not a fix for your problem. This is just for illustrating the problem.
You have two threads racing: one writes values of current_thread_state twice, another reads the value of current_thread_state once.
It is indeterminate whether the sequence of events is write-write-read or write-read-write as you expect, both are valid executions of your application.

Including a ping timeout feature

I have Server A that receive's updates from Server B. I would like to add functionality to Server A where if it does not receive a message(server B will send update and ping messages) in 1 minutes time, Server A will go into a paused state and wait for messages to come in again.
I was looking into a boost::asio::deadline_timer, but I cannot figure out if it is possible, or if you can run this asynchronously. I tried a class that runs in its own thread and uses a deadline timer, but I am unable to cancel and restart the deadline timer. Here is some example code I used for that.
The implementation:
void ping_timeout::reset_timer()
{
ping_timeout_.cancel();
ping_timeout_.expires_from_now(boost::posix_time::seconds(60));
//Call to clear the cache of a static class, which is the paused state I would like
ping_timeout_.async_wait(boost::bind(&cache::empty_cache));
io_.run();
}
I am unable to cancel the deadline timer from my main thread of execution by calling reset timer, I am guessing because io_.run() is waiting for the 60 seconds to expire.
Is there any modification I can do, any any libraries out there that I can us to achieve the results I would like? Any help would be appreciated.
Thank you
Edit:
Main Loop:
ping_timeout timeout;
boost::thread(boost::bind(&cache::run_io,boost::ref(service)));
while(true)
{
std::string message = s_recv(subscriber);
}
if(message.compare("UPDATE") == 0)
{
//Process update
}
else if(message.compare("PING") == 0)
{
timeout.reset_timer();
}
}
Edit 2:
Working code:
void cache::process_cache()
{
boost::asio::io_service service;
boost::asio::io_service::work work(service);
boost::thread(boost::bind(&cache::run_io,boost::ref(service)));
boost::asio::deadline_timer timer(service,boost::posix_time::seconds(60));
timer.async_wait(boost::bind(&cache::empty_cache,boost::asio::placeholders::error));
while(true)
{
std::string message = s_recv(subscriber);
if(message.compare("UPDATE") == 0)
{
//Process update
}
else if(message.compare("PING") == 0)
{
timer.cancel();
timer.expires_from_now(boost::posix_time::seconds(60));
timer.async_wait(boost::bind(&cache::empty_cache,boost::asio::placeholders::error));
}
}
}
void cache::empty_cache(const boost::system::error_code& e)
{
if(e.value() == 0)
{
//Clear cache
}
}
void cache::run_io(boost::asio::io_service& io)
{
io.run();
}
boost::asio::io_service::run() is a blocking call. In your specific case, you should avoid calling that in your main thread.
Note: In a typical async-driven app, you should build your app around the run method.
As for the timer code logic, something like that should work :
boost::asio::io_service service;
// Creates a work object to prevent the thread from exiting after the first job is done
boost::asio::io_service::work work(service);
// Creates the timer and post the aync wait now, will only start when service.run() is called
boost::asio::deadline_timer timer(service, boost::posix_time::seconds(60));
timer.async_wait(boost::bind(&cache::empty_cache, ...));
// Starts the worker thread to allow the timer to asynchronously waits
boost::thread ping_thread(boost::bind(&boost::asio::io_service::run, &service));
while (true) // you should add a condition in order to leave if the timer expires
{
std::string message = s_recv(subscriber);
/**/ if (message == "UPDATE")
{
// Process update
}
else if (message == "PING")
{
// Cancel the current timer
timer.cancel();
// Start another async wait
timer.async_wait(boost::bind(&cache::empty_cache, ...));
}
}

Where to destroy thread and deadline_timer objects after timeout?

my question is about a running deadline timers which wait for some operations represented by the same function to finish: But i dont't know, where to free my thread and deadline object after a safe finish oder an interrupt by deadline time out. When can that happen?
boost::asio::deadline_timer* mDeadline1;
boost::asio::deadline_timer* mDeadline2;
boost::thread* mThread1;
boost::thread* mThread2;
// start deadline timers
mDeadline1 = new boost::asio::deadline_timer(_io_service, boost::posix_time::seconds(2));
mDeadline1->async_wait(&MyClass::DeadlineTimedOut, this);
mDeadline2 = new boost::asio::deadline_timer(_io_service, boost::posix_time::seconds(2));
mDeadline2->async_wait(&MyClass::DeadlineTimedOut, this);
// Run operations in threads
mThread1 = new boost::thread(&MyClass::DoSomething, this);
mThread2 = new boost::thread(&MyClass::DoSomething, this);
// ...
void MyClass::DoSomething() {
// Do something time expensive and sleep, etc. for interrupt point ...
// which to cancel here!?
mDeadline->cancel();
delete mDeadline;
}
void MyClass::DeadlineTimedOut(const boost::system::error_code& pErrorCode) {
if(pErrorCode == 0) { // deadline timed out
// which to interrupt here?
mThread->interrupt();
}
if(pErrorCode == 995) { // deadline cancelled from outside
}
}
Has anyone some advice? Graceful, B.
The timers as they stand are meaningless - only you know what they mean and what they are supposed to do - so you have to decide what to cancel. As to cleaning up, hold them in a scoped_ptr or shared_ptr and they will be automagically cleaned up when the scope/last reference is done.