java - avoid unnessary thread wake-ups - multithreading

I have a set of 12 threads executing work (Runnable) in parallel. In essence, each thread does the following:
Runnable r;
while (true) {
synchronized (work) {
while (work.isEmpty()) {
work.wait();
}
r = work.removeFirst();
}
r.execute();
}
Work is added as following:
Runnable r = ...;
synchronized (work) {
work.add(r);
work.notify();
}
When new work is available, it is added to the list and the lock is notified. If there is a thread waiting, it is woken up, so it can execute this work.
Here lies the problem. When a thread is woken up, it is very likely that another thread will execute this work. This happens when the latter thread is done with its previous work and re-enters the while(true)-loop. The smaller/shorter the work actions, the more likely this will happen.
This means I am waking up a thread for nothing. As I need high throughput, I believe this behavior will lower the performance.
How would you solve this? In theory, I need a mechanism which allows me to cancel a pending thread wake-up notification. Of course, this is not possible in Java.
I thought about introducing a work list for each thread. Instead of pushing the work into one single list, the work is spread over the 12 work lists. But I believe this will introduce other problems. For example, one thread might have a lot of work pending, while another thread might have no work pending. In essence, I believe that a solution which assigns work to a particular thread in advance might become very complex and and is sub-optimal.
Thanks!

What you are doing is a thread pooling. Take a look at pre java-5 concurrency framework, PooledExecutor class there:
http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html

In addition to my previous answer - another solution. This question makes me curious.
Here, I added a check with volatile boolean.
It does not completely avoid the situation of uselessly wakening up a thread but helps to avoid it. Actually, I do not see how this could be completely avoided without additional restrictions like "we know that after 100ms a job will most likely be done".
volatile boolean free = false;
while (true) {
synchronized (work) {
free = false; // new rev.2
while (work.isEmpty()) {
work.wait();
}
r = work.removeFirst();
}
r.execute();
free = true; // new
}
--
synchronized (work) {
work.add(r);
if (!free) { // new
work.notify();
} // new
free = false; // new rev.2
}

Related

why does std::condition_variable::wait need mutex?

TL;DR
Why does std::condition_variable::wait needs a mutex as one of its variables?
Answer 1
You may look a the documentation and quote that:
wait... Atomically releases lock
But that's not a real reason. That's just validate my question even more: why does it need it in the first place?
Answer 2
predicate is most likely query the state of a shared resource and it must be lock guarded.
OK. fair.
Two questions here
Is it always true that predicate query the state of a shared resource? I assume yes. I t doesn't make sense to me to implement it otherwise
What if I do not pass any predicate (it is optional)?
Using predicate - lock makes sense
int i = 0;
void waits()
{
std::unique_lock<std::mutex> lk(cv_m);
cv.wait(lk, []{return i == 1;});
std::cout << i;
}
Not Using predicate - why can't we lock after the wait?
int i = 0;
void waits()
{
cv.wait(lk);
std::unique_lock<std::mutex> lk(cv_m);
std::cout << i;
}
Notes
I know that there are no harmful implications to this practice. I just don't know how to explain to my self why it was design this way?
Question
If predicate is optional and is not passed to wait, why do we need the lock?
When using a condition variable to wait for a condition, a thread performs the following sequence of steps:
It determines that the condition is not currently true.
It starts waiting for some other thread to make the condition true. This is the wait call.
For example, the condition might be that a queue has elements in it, and a thread might see that the queue is empty and wait for another thread to put things in the queue.
If another thread were to intercede between these two steps, it could make the condition true and notify on the condition variable before the first thread actually starts waiting. In this case, the waiting thread would not receive the notification, and it might never stop waiting.
The purpose of requiring the lock to be held is to prevent other threads from interceding like this. Additionally, the lock must be unlocked to allow other threads to do whatever we're waiting for, but it can't happen before the wait call because of the notify-before-wait problem, and it can't happen after the wait call because we can't do anything while we're waiting. It has to be part of the wait call, so wait has to know about the lock.
Now, you might look at the notify_* methods and notice that those methods don't require the lock to be held, so there's nothing actually stopping another thread from notifying between steps 1 and 2. However, a thread calling notify_* is supposed to hold the lock while performing whatever action it does to make the condition true, which is usually enough protection.
TL;DR
If predicate is optional and is not passed to wait, why do we need the lock?
condition_variable is designed to wait for a certain condition to come true, not to wait just for a notification. So to "catch" the "moment" when the condition becomes true you need to check the condition and wait for the notification. And to avoid a race condition you need those two to be a single atomic operation.
Purpose Of condition_variable:
Enable a program to implement this: do some action when a condition C holds.
Intended Protocol:
Condition producer changes state of the world from !C to C.
Condition consumer waits for C to happen and takes the action while/after condition C holds.
Simplification:
For simplicity (to limit number of cases to think of) let's assume that C never switches back to !C. Let's also forget about spurious wakeups. Even with this assumptions we'll see that the lock is necessary.
Naive Approach:
Let's have two threads with an essential code summarized like this:
void producer() {
_condition = true;
_condition_variable.notify_all();
}
void consumer() {
if (!_condition) {
_condition_variable.wait();
}
action();
}
The Problem:
The problem here is a race condition. A problematic interleaving of the threads is following:
The consumer reads condition, checks it to be false and decides to wait.
A thread scheduler interrupts consumer and resumes producer.
The producer updates condition to become true and invokes notify_all().
The consumer is resumed.
The consumer actually does wait(), but is never notified and waken up (a liveness hazard).
So without locking the consumer may miss the event of the condition becoming true.
Solution:
Disclaimer: this code still does not handle spurious wakeups and possibility of condition becoming false again.
void producer() {
{ std::unique_lock<std::mutex> l(_mutex);
_condition = true;
}
_condition_variable.notify_all();
}
void consumer() {
{ std::unique_lock<std::mutex> l(_mutex);
if (!_condition) {
_condition_variable.wait(l);
}
}
action();
}
Here we check condition, release lock and start waiting as a single atomic operation, preventing the race condition mentioned before.
See Also
Why Lock condition await must hold the lock
You need a std::unique_lock when using std::condition_variable for the same reason you need a std::FILE* when using std::fwrite and for the same reason a BasicLockable is necessary when using std::unique_lock itself.
The feature std::fwrite gives you, entire the reason it exists, is to write to files. So you have to give it a file. The feature std::unique_lock provides you is RAII locking and unlocking of a mutex (or another BasicLockable, like std::shared_mutex, etc.) so you have to give it something to lock and unlock.
The feature std::condition_variable provides, the entire reason it exists, is the atomically waiting and unlocking a lock (and completing a wait and locking). So you have to give it something to lock.
Why would someone want that is a separate question that has been discussed already. For example:
When is a condition variable needed, isn't a mutex enough?
Conditional Variable vs Semaphore
Advantages of using condition variables over mutex
And so on.
As has been explained, the pred parameter is optional, but having some sort of a predicate and testing it isn't. Or, in other words, not having a predicate doesn't make any sense inn a manner similar to how having a condition variable without a lock doesn't making any sense.
The reason you have a lock is because you have shared state you need to protect from simultaneous access. Some function of that shared state is the predicate.
If you don't have a predicate and you don't have a lock you really don't need a condition variable just like if you don't have a file you really don't need fwrite.
A final point is that the second code snippet you wrote is very broken. Obviously it won't compile as you define the lock after you try to pass it as an argument to condition_variable::wait(). You probably meant something like:
std::mutex mtx_cv;
std::condition_variable cv;
...
{
std::unique_lock<std::mutex> lk(mtx_cv);
cv.wait(lk);
lk.lock(); // throws std::system_error with an error code of std::errc::resource_deadlock_would_occur
}
The reason this is wrong is very simple. condition_variable::wait's effects are (from [thread.condition.condvar]):
Effects:
— Atomically calls lock.unlock() and blocks on *this.
— When unblocked, calls lock.lock() (possibly blocking on the lock), then returns.
— The function will unblock when signaled by a call to notify_one() or a call to notify_all(), or spuriously
After the return from wait() the lock is locked, and unique_lock::lock() throws an exception if it has already locked the mutex it wraps ([thread.lock.unique.locking]).
Again, why would someone want coupling waiting and locking the way std::condition_variable does is a separate question, but given that it does - you cannot, by definition, lock a std::condition_variable's std::unique_lock after std::condition_variable::wait has returned.
It's not stated in the documentation (and could be implemented differently) but conceptually you can imagine the condition variable has another mutex to both protect its own data but also coordinate the condition, waiting and notification with modification of the consumer code data (e.g. queue.size()) affecting the test.
So when you call wait(...) the following (logically) happens.
Precondition: The consumer code holds the lock (CCL) controlling the consumer condition data (CCD).
The condition is checked, if true, execution in the consumer code continues still holding the lock.
If false, it first acquires its own lock (CVL), adds the current thread to the waiting thread collection releases the consumer lock and puts itself to waiting and releases its own lock (CVL).
That final step is tricky because it needs to sleep the thread and release the CVL at the same time or in that order or in a way that threads notified just before going to wait are able to (somehow) not go to wait.
The step of acquiring the CVL before releasing the CCD is key. Any parallel thread trying to update the CCD and notify will be blocked either by the CCL or CVL. If the CCL was released before acquiring the CVL a parallel thread could acquire the CCL, change the data and then notify before the the to-be-waiting thread is added to the waiters.
A parallel thread acquires the CCL, modifies the data to make the condition true (or at least worth testing) and then notifies. Notification acquires the the CVL and identifies a blocked thread (or threads) if any to unwait. The unwaited threads then seek to acquire the CCL and may block there but won't leave wait and re-perform the test until they've acquired it.
Notification must acquire the CVL to make sure threads that have found the test false have been added to the waiters.
It's OK (possibly preferable for performance) to notify without holding the CCL because the hand-off between the CCL and CVL in the wait code is ensuring the ordering.
It may be preferrable because notifying when holding the CCL may mean all the unwaited threads just unwait to block (on the CCL) while the thread modifying the data is still holding the lock.
Notice that even if the CCD is atomic you must modify it holding the CCL or that Lock CVL, unlock CCL step won't ensure the total ordering required to make sure notifications aren't sent when threads are in the process of going to wait.
The standard only talks about atomicity of operations and another implementation may have a way of blocking notification before completing the 'add to waiters' step has completed following a failed test. The C++ Standard is careful to not dictate an implementation.
In all that, to answer some of the specific questions.
Must the state be shared? Sort of. There could be an external condition like a file being in a directory and the wait is timed to re-try after a time-period. You can decide for yourself whether you consider the file system or even just the wall-clock to be shared state.
Must there be any state? Not necessarily. A thread can wait on notification.
That could be tricky to coordinate because there has to be enough sequencing to stop the other thread notifying out of turn. The commonest solution is to have some boolean flag set by the notifying thread so the notified thread knows if it missed it. The normal use of void wait(std::unique_lock<std::mutex>& lk) is when the predicate is checked outside:
std::unique_lock<std::mutex> ulk(ccd_mutex)
while(!condition){
cv.wait(ulk);
}
Where the notifying thread uses:
{
std::lock_guard<std::mutex> guard(ccd_mutex);
condition=true;
}
cv.notify();
The reason is that in some times the waiting-thread holds the m_mutex:
#include <mutex>
#include <condition_variable>
void CMyClass::MyFunc()
{
std::unique_lock<std::mutex> guard(m_mutex);
// do something (on the protected resource)
m_condiotion.wait(guard, [this]() {return !m_bSpuriousWake; });
// do something else (on the protected resource)
guard.unluck();
// do something else than else
}
and a thread should never go to sleep while holding a m_mutex. One doesn't want to lock everybody out, while sleeping. So, atomically: {guard is unlocked and the thread go to sleep}. Once it waked up by the other-thread (m_condiotion.notify_one(), let's say) guard is locked again, and then the thread continue.
Reference (video)
Because if not so, there's a race condition before the waiting thread noticing the change of the shared state and the wait() call.
Assume we got a shared state of type std::atomic state_, there's still a fair chance for the waiting thread to miss a notification:
T1(waiting) | T2(notification)
---------------------------------------------- * ---------------------------
1) for (int i = state_; i != 0; i = state_) { |
2) | state_ = 0;
3) | cv.notify();
4) cv.wait(); |
5) }
6) // go on with the satisfied condition... |
Note that the wait() call failed to notice the latest value of state_ and may keep waiting forever.

ReleaseMutex : Object synchronization method was called from an unsynchronized block of code

I have this pretty straightforward piece of code that very rarely throws "System.ApplicationException : Object synchronization method was called from an unsynchronized block of code." when ReleaseMutex() is called.
I logically analyzed the flow of the method and just cannot understand how/why this could happen.
To my understanding, the ownership of mutex is guaranteed in this case:
readonly string mutexKey;
public Logger(string dbServer, string dbName)
{
this.mutexKey = ServiceManagerHelper.GetServiceName(dbServer, dbName);
}
private void Log(LogType type, string message, Exception ex)
{
using (var mutex = new Mutex(false, mutexKey))
{
bool acquiredMutex;
try
{
acquiredMutex = mutex.WaitOne(TimeSpan.FromSeconds(5));
}
catch (AbandonedMutexException)
{
acquiredMutex = true;
}
if (acquiredMutex)
{
try
{
// some application code here
}
finally
{
mutex.ReleaseMutex();
}
}
}
}
catch (AbandonedMutexException)
{
acquiredMutex = true;
}
This is a very serious bug in your code. Catching an AbandonedMutexException is never correct, it is a very serious mishap. Another thread acquired the mutex but terminated without calling ReleaseMutex(). You've irrecoverably lost synchronization and the mutex is no longer usable.
You were sort of lucky by making a mistake and assuming that you acquired the mutex anyway. You didn't. The ReleaseMutex() call will now bomb with the exception you quoted.
You cannot recover from this mishap, other than by terminating the program (the wise choice) or by disabling logging completely so the mutex will never be used again. Make the wise choice by removing the catch clause. Discovering the true source of the problem, that thread that crashed and didn't call ReleaseMutex(), is out of context for this question, there are no hints. You've been ignoring this problem, papered it over by catching AME, you can't ignore it.
In my case, i see the same behavior like Nathan Schubkegel. I use await's, and Thread.CurrentThread.ManagedThreadId gives another value for the "same" thread. I mean, thread was started with ManagedThreadId == 10, and Mutex was owned with this thread id, but later ReleaseMutex() causes ApplicationException with message: "Object synchronization method was called from an unsynchronized block of code", and i see that ManagedThreadId == 11 at this time :) . It seems, await sometimes changes thread id when returns. It seems, that is the reason. Mutex thinks that another thread wants to release it. It's sad, that Mutex documentation does not make ATTENTION on this moment.
So, you CAN NOT use asynchronous operator await between Mutex acquire and release. It's because C# compiler replaces plain operator await by asynchronous callback, and this callback can be made by ANOTHER thread. Usually, it's the same thread, but sometimes it's another thread (from thread pool).
Mutex checks thread. Only thread that acquired Mutex may release it. If you need synchronization without this checking, use Semaphore. SemaphoreSlim has asynchronous method WaitAsync() - it's cool.
This exception is raised when you call ReleaseMutex() from a thread that does not own the mutex. Search // some application code here for code that releases the mutex.
Also reconsider whether you're actually calling ReleaseMutex() from the same thread where you called WaitOne(). Example: I arrived at this post because I was using async/await and my code resumed on a different thread and tried to release a mutex the thread didn't own.

Spawn a thread and worker queue only if resource is busy

Hoping someone can help me design this correctly.
In my TCP code, I have a SendMessage() function that tries to write to the wire. I am trying to design the call so that it moves to a producer/consumer model if a lot of concurrent requests happen, but at the same time, stays single-threaded if there are no concurrent requests (for maximum performance).
I'm struggling on how to design this without race conditions because there is no way to move locks between threads.
What I have so far is something like (pseudo-coded):
SendMessage(msg) {
if(Monitor.TryEnter(wirelock,200)) {
try{
sendBytes(msg);
}
finally {
Monitor.Exit...
}
}
else {
_SomeThreadSafeQueue.add(msg)
Monitor.TryEnter(consumerlock,..
Task.Factory.New(ConsumerThreadMethod....
}
}
ConsumerThreadMethod() {
lock (wirelock) {
while(therearemessagesinthequeue)
sendBytes...
}
}
Any obvious race conditions?
EDIT: Found a flaw in the last one. How about this instead?
SendMessage(msg) {
if(Monitor.TryEnter(wirelock)) {
try{
sendBytes(msg);
}
finally {
Monitor.Exit...
}
}
else {
_SomeThreadSafeQueue.add(msg)
if (Interlocked.Increment(ref _threadcounter) == 1)
{
Task.Factory.StartNew(() => ConsumerThreadMethod());
}
else
{
Interlocked.Decrement(ref _threadcounter);
}
}
}
ConsumerThreadMethod() {
while(therearemessagesinthequeue)
lock (wirelock) {
sendBytes...
}
}
Interlocked.Decrement(ref _threadcounter);
}
So basically using the interlocked counter as a way to only ever spawn one thread (if necessary)
No obvious races but TryEnter is a cause for some serious idle time. I actually think that using a consumer thread all the time is the best solution. If there is little to do, the overhead will be really small (the consumer thread will be asleep when not working, if designed correctly).
Now you create a new task for each sent message, resulting in huge contention on the lock, since you are using a while loop in the consumer thread.
EDIT: Since you are using non-blocking sockets, a single consumer thread should be enough to handle all send requests. The throughput of a single thread is higher than your network. If you have more consumers it's hard to make sure that no two consumer threads send on the same socket, without serializing everything using a mutex. I don't think switching between single-threaded and multi-threaded is a good idea.
Your current "multithreaded" solution does not give you any performance gain since all work is protected using the same mutex. It will be as slow, or slower, than a single thread.

Correct Usage Of System.Threading.Timer

I stumbled across some code similar to below:
private void SomeCallBack(object state)
{
lock (_lock)
{
try
{
if (_timer == null)
return;
_timer.Dispose();
// do some work here
}
catch
{
// handle exception
}
finally
{
_timer = new Timer(SomeCallBack, state, 100, Timeout.Infinite);
}
}
}
I don't understand the purpose of recreating the timer every time the callback is executed. I think what the code is trying to achieve is that only one thread can perform the work at a time. But wouldn't the lock be sufficient?
Also, according to msdn,
Note that callbacks can occur after the Dispose() method overload has been called
Is there any benefits of doing this?
If so, do the benefits justify the overheads in disposing and creating the timer?
Thanks for your help.
It seems that the code wants a nearly periodic timer (not exactly periodic because of the jitter introduced by the processing between the expiration of the timer and creation of the new timer). Disposing and recreating the timer is indeed an unnecessary overhead. The Change method would be better.
The check for null is also curious; somewhere else there would have to be code that sets _timer null for it to have any effect.
The reason for recreating the timer would be for the scenario where the code in the timer callback takes longer to execute than the timer period. In this case multiple instances of the callback would be running at the same time.

When myThread.Start(...) is called, do we have the assurance that the thread is started?

When myThread.Start(...) is called, do we have the assurance that the thread is started? The MSDN documentation isn't really specific about that. It says that the status of is changed to Running.
I am asking because I've seen a couple of times the following code. It creates a thread, starts it and then loop until the status become Running. Is that necessary to loop?
Thread t = new Thread(new ParameterizedThreadStart(data));
t.Start(data);
while (t.ThreadState != System.Threading.ThreadState.Running &&
t.ThreadState != System.Threading.ThreadState.WaitSleepJoin)
{
Thread.Sleep(10);
}
Thanks!
If you're set on not allowing your loop to continue until the thread has "started", then it will depend on what exactly you mean by "started". Does that mean that the thread has been created by the OS and signaled to run, but not necessarily that it's done anything yet? Does that mean that it's executed one or more operations?
While it's likely fine, your loop isn't bulletproof, since it's theoretically possible that the entire thread executes between the time you call Start and when you check the ThreadState; it's also not a good idea to check the property directly twice.
If you want to stick with checking the state, something like this would/could be more reliable:
ThreadState state = t.ThreadState;
while(state != ThreadState.Runnung && state != ThreadState.WaitSleepJoin)
{
Thread.Sleep(10:
state = t.ThreadState;
}
However, this is still subject to the possibility of the thread starting, running, then stopping before you even get the chance to check. Yes, you could expand the scope of the if statement to include other states, but I would recommend using a WaitHandle to signal when the thread "starts".
ManualResetEvent signal;
void foo()
{
Thread t = new Thread(new ParameterizedThreadStart(ThreadMethod));
signal = new ManualResetEvent();
t.Start(data);
signal.WaitOne();
/* code to execute after the thread has "started" */
}
void ThreadMethod(object foo)
{
signal.Set();
/* do your work */
}
You still have the possiblity of the thread ending before you check, but you're guaranteed to have that WaitHandle set once the thread starts. The call to WaitOne will block indefinitely until Set has been called on the WaitHandle.
Guess it depends on what you are doing after the loop. If whatever comes after it critically dependant on the thread running then checking is not a bad idea. Personnally I'd use a ManualResetEvent or something similiar that was set by the Thread rather than checking the ThreadStatus
No. Thread.Start causes a "thread to be scheduled for execution". It will start, but it may take a (short) period of time before the code within your delegate actually runs. In fact, the code above doesn't do what (I suspect) the author intended, either. Setting the thread's threadstate to ThreadState.Running (which does happen in Thread.Start) just makes sure it's scheduled to run -- but the ThreadState can be "Running" before the delegate is actually executing.
As John Bergess suggested, using a ManualResetEvent to notify the main thread that the thread is running is a much better option than sleeping and checking the thread's state.

Resources