I currently have a program running with about 20 threads at a time. I am fairly new to multi-threading so I'm a little confused on proper data protection.
Currently, my threads use Events as data locks an unlocks. I opted to use this over critical sections as most data is only shared between two or three threads so preventing a single thread from reading while one wrote by stopping all 20 threads seemed wasteful. I used Event over Mutex simply due to the fact that I could not (easily) find a source that clearly explained how a Mutex works and how to implement one.
I'm using Win32 API for my multi-threading. In my current setup I use Events to lock data so my event would be something like "DataUnlock" When not set I know that the data is being worked on. When set I know it is ok to work on the data. So my makeshift data locks look something like this.
WaitForSingleObject( DataUnlock,INFINITE ); //Wait until the Data is free
ResetEvent(DataUnlock); //Signal that the data is being worked on
...work on Data...
SetEvent(DataUnlock); //Signal that the data is free to use
My first question is: Is this as good (efficient) as using a Mutex when only two threads are accessing the data?
Second: If more than two threads waiting to access the data is there a potential that both will be triggered when the data is freed (will the both pass the wait before one reaches ResetEvent)? If so, would a mutex have the same issue?
Lastly: If a mutex is preferable, how would I go about implementing one (a link or explanation would be greatly appreciated)?
Thanks!
I don't think that the event approach is the best way of protecting the data.
Look at Mutex Objects and Using Mutex Objects to learn about mutexes.
One of your threads has to create a mutex. The CreateMutex function returns a handle to the mutex object. You can pass the handle as an argument to the threads dealing with your data.
Use the WaitForSingleObject function to wait for the mutex and then process your data. Release the mutex with a call to the ReleaseMutex function. When a mutex is released the next wait function will gain the mutex.
In case the data is to be accessed by threads of multiple processes, named mutexes have to be used.
Look at Critical Section Objects to learn about critical section synchronisation.
If you want to have the
A critical section has to be created by a call to the InitializeCriticalSection function.
Use the EnterCriticalSection function at all places before you handle your data.
The LeaveCriticalSection function releases the critical section releases the object. Use this call after you're done with the data.
The critical section can only be entered by the owning thread. Once a thread has gained the critical section object, no other thread can get access to your data. Other threads will block at the call to EnterCriticalSection(). However the thread owns the critical section can do succesive calls to EnterCriticalSection() more than once. Care shall be taken to call LeaveCriticalSection() once for every call to EnterCriticalSection().
Your example would let all threads waiting for the event process your data. And you would only know by the data themself if processing of anykind has happened. That's up to you,
how to determine what was done and what still needs to be done. If you have many threads waiting for your event, you can't tell the order in which the get access.
I would recommend using a critical section object. It is lightweight and relatively easy to use. See Using Critical Section Objects for an example how to use critical section objects.
Related
Suppose we have a cache with a CacheLoaderWriter, so we are registered to the events: write and writeAll.
What is the status of these keys at that time?
i.e. If another thread tries to cache.get(keyThatBeingWritten), will it be blocked until the write()/writeAll() operations exit?
writeAll() logically functions like a succession of write(), it is entirely possible for one thread to observe some already written data while another thread is still busy executing writeAll().
Regarding write(), it will block concurrent reader and writer threads working on the same key if needed for as long as needed to fulfill the Ehcache visibility guarantees.
I'm making a little server for a project, I have a log handler class which contains a log implemented as a map and some methods to act on it (add entry, flush to disk, commit etc..)
This object is instantiated in the server Class, and I'm passing the address to the session so each session can add entries to it.
The sessions are async, the log writes will happen in the async_read callback. I'm wondering if this will be an issue and if i need to use locks?
The map format is map<transactionId map<sequenceNum, pair<head, body>>, each session will access a different transactionId, so there should be no clashes as far as i can figure. Also hypothetically, if they were all writing to the same place in memory -- something large enough that the operation would not be atomic; would i need locks? As far as I understand each async method dispatches a thread to handle the operation, which would make me assume yes. At the same time I read that one of the great uses of async functions is the fact that synchronization primitives are not needed. So I'm a bit confused.
First time using ASIO or any type of asynchronous functions altogether, and i'm not a very experienced coder. I hope the question makes sense! The code seems to run fine so far, but i'm curios if it's correct.
Thank you!
Asynchronous handlers will only be invoked in application threads processing the io_service event loop via run(), run_one(), poll(), or poll_one(). The documentation states:
Asynchronous completion handlers will only be called from threads that are currently calling io_service::run().
Hence, for a non-thread safe shared resource:
If the application code only has one thread, then there is neither concurrency nor race conditions. Thus, no additional form of synchronization is required. Boost.Asio refers to this as an implicit strand.
If the application code has multiple threads processing the event-loop and the shared resource is only accessed within handlers, then synchronization needs to occur, as multiple threads may attempt to concurrently access the shared resource. To resolve this, one can either:
Protect the calls to the shared resource via a synchronization primitive, such as a mutex. This question covers using mutexes within handlers.
Use the same strand to wrap() the ReadHandlers. A strand will prevent concurrent invocation of handlers dispatched through it. For more details on the usage of strands, particularly for composed operations, such as async_read(), consider reading this answer.
Rather than posting the entire ReadHandler into the strand, one could limit interacting with the shared resource to a specific set of functions, and these functions are posted as CompletionHandlers to the same strand. This subtle difference between this and the previous solution is the granularity of synchronization.
If the application code has multiple threads and the shared resource is accessed from threads processing the event loop and from threads not processing the event loop, then synchronization primitives, such as a mutex, needs to be used.
Also, even if a shared resource is small enough that writes and reads are always atomic, one should prefer using explicit and proper synchronization. For example, although the write and read may be atomic, without proper memory fencing to guarantee memory visibility, a thread may not observe a chance in memory even though the actual memory has chanced. Boost.Asio's will perform the proper memory barriers to guarantee visibility. For more details, on Boost.Asio and memory barriers, consider reading this answer.
What is the advantage/disadvantage over using RegisterWaitForSingleObject() instead of WaitForSingleObject()?
The reason that I know:
RegisterWaitForSingleObject() uses the thread pool already available in OS
In case of the use of WaitForSingleObject(), an own thread should be polling for the event.
the only difference is Polling vs. Automatic Event? or Is there any considerable performance advantage between these?
It's pretty straight-forward, WaitForSingleObject() blocks a thread. It is consuming a megabyte of virtual memory and not doing anything useful with it while it is blocked. It won't wake up and resume doing useful stuff until the handle is signaled.
RegisterWaitForSingleObject() does not block a thread. The thread can continue doing useful work. When the handle is signaled, Windows grabs a thread-pool thread to run the code you specified as the callback. The same code you would have programmed after a WFSO call. There is still a thread involved with getting that callback to run, the wait thread, but it can handle many RWFSO requests.
So the big advantage is that your program can use a lot less threads while still handling many service requests. A disadvantage is that it can take a bit longer for the completion code to start running. And it is harder to program correctly since that code runs on another thread. Also note that you don't need RWFSO when you already use overlapped I/O.
They serve two different code models. In case with RegisterWaitForSingleObject you'll get an asynchronous notification callback on a random thread from the thread pool managed by the OS. If you can structure your code like this, it might be more efficient. On the other hand, WaitForSingleObject is a synchronous wait call blocking (an thus 'occupying') the calling thread. In most cases, such code is easier to write and would probably be less error-prone to various dead-lock and race conditions.
I'm working on a DirectShow filter which takes input samples and turns them into modified output samples but where there isn't a one-to-one correspondence between input and output samples so CTransformFilter doesn't seem to be the way to go.
The best way of writing this appears to be writing a filter using CBaseFilter, CBaseInputPin and CBaseOutputPin where samples are received on an input pin and processed by a worker thread which creates and delivers new samples from the output pin. The worker thread copies the input sample data before starting work so that my filter doesn't have to maintain a reference to the input samples outside the input CBaseInputPin::Receive call.
What's the best practice for maintaining thread safety and avoiding deadlocks in this case? Should the input and output pin share the same streaming lock or should they have a streaming lock each for their streaming operations? Do buffer allocation, sample delivery and other output pin operations need to hold the streaming lock(s) and/or the filter lock? Any sample code that does something similar? Any other gotchas to watch out for in this situation?
The DirectShow bases classes contain scary comments for CBaseOutputPin::Deliver and CBaseOutputPin::GetDeliveryBuffer which I don't fully understand (pasted below).
/* Deliver a filled-in sample to the connected input pin. NOTE the object must
have locked itself before calling us otherwise we may get halfway through
executing this method only to find the filter graph has got in and
disconnected us from the input pin. If the filter has no worker threads
then the lock is best applied on Receive(), otherwise it should be done
when the worker thread is ready to deliver. There is a wee snag to worker
threads that this shows up. The worker thread must lock the object when
it is ready to deliver a sample, but it may have to wait until a state
change has completed, but that may never complete because the state change
is waiting for the worker thread to complete. The way to handle this is for
the state change code to grab the critical section, then set an abort event
for the worker thread, then release the critical section and wait for the
worker thread to see the event we set and then signal that it has finished
(with another event). At which point the state change code can complete */
You have a few samples in Windows SDK in \Samples\multimedia\directshow\filters and earlier version of SDK had even more. This would be perhaps the best sample code you can check for locking practices.
The filter and pins normally use shared critical sections to ensure thread safety. For instance, CTransformFilter::m_csFilter protects the state data of the filter and not only section, but pins also use the section. The additional section is also used to serialize streaming requests (pushing through samples, sending EOS notifications).
Your filter might be using state critical section, or you can alternatively use additional synchronization object (section, reader-writer lock, or a mutex) in order to avoid deadlocks with critical section being possibly locked by base classes.
Regular suggestions apply: to avoid deadlocks you should make sure your locking order is designed in a way that if section A can be locked on a thread which already has section B locked, you should only lock B [on other threads] when without existing lock on A, so that no deadlock is possible.
So typically, you have two scenarios which most use cases fall into:
you are reusing state critical section of the filter
you are using a separate critical section which protects your private data, and you don't keep the section locked while doing calls on base class methods and methods of other object such as peer filters
I've created two threads A & B using CreateThread windows API. I'm trying to send the data from thread A to B.
I know I can use Event object and wait for the Event object in another using "WaitForSingleObject" method. What this event does all is just signal the thread. That's it! But how I can send a data. Also I don't want thread B to wait till thread A signals. It has it own job to do. I can't make it wait.
I can't find a Windows function that will allow me to send data to / from the worker thread and main thread referencing the worker thread either by thread ID or by the returned HANDLE. I do not want to introduce the MFC dependency in my project and would like to hear any suggestions as to how others would or have done in this situation. Thanks in advance for any help!
First of all, you should keep in mind that Windows provides a number of mechanisms to deal with threading for you: I/O Completion Ports, old thread pools and new thread pools. Depending on what you're doing any of them might be useful for your purposes.
As to "sending" data from one thread to another, you have a couple of choices. Windows message queues are thread-safe, and a a thread (even if it doesn't have a window) can have a message queue, which you can post messages to using PostThreadMessage.
I've also posted code for a thread-safe queue in another answer.
As far as having the thread continue executing, but take note when a change has happened, the typical method is to have it call WaitForSingleObject with a timeout value of 0, then check the return value -- if it's WAIT_OBJECT_0, the Event (or whatever) has been set, so it needs to take note of the change. If it's WAIT_TIMEOUT, there's been no change, and it can continue executing. Either way, WaitForSingleObject returns immediately.
Since the two threads are in the same process (at least that's what it sounds like), then it is not necessary to "send" data. They can share it (e.g., a simple global variable). You do need to synchronize access to it via either an event, semaphore, mutex, etc.
Depending on what you are doing, it can be very simple.
Thread1Func() {
Set some global data
Signal semaphore to indicate it is available
}
Thread2Func() {
WaitForSingleObject to check/wait if data is available
use the data
}
If you are concerned with minimizing Windows dependencies, and assuming you are coding in C++, then I recommend using Boost.Threads, which is a pretty nice, Posix-like C++ threading interface. This will give you easy portability between Windows and Linux.
If you go this route, then use a mutex to protect any data shared across threads, and a condition variable (combined with the mutex) to signal one thread from the other.
DonĀ“t use a mutexes when only working in one single process, beacuse it has more overhead (since it is a system-wide defined object)... Place a critical section around Your data and try to enter it (as Jerry Coffin did in his code around for the thread safe queue).