Mistake # 1: Not using join() to wait for background threads before terminating an application
If we forgot to join a thread or detach it(make it unjoinable) before the main program terminates, it'll cause in a program crash.
Mistake # 2: Trying to join a thread that has been previously detached
If you have detached a thread and at some point, you cannot rejoin it to the main thread.
The problem is that this'll not cause a compilation error, instead it'll crash your program.
Mistake # 3: Not realizing that std::thread::join() blocks the calling thread
Mistake # 4: Thinking that thread function arguments are pass by reference by default
Thread function arguments are by default pass by value. So if you need the change persisted in the arguments passed in, you'll need to pass them by reference using std::ref().
Mistake # 5: Not protecting shared data or shared resources with a critical section (eg. mutex)
In a multithreaded environment, more than one thread is often competing for a resource or shared data. This often results in undefined behavior for the resource or data , unless the resource or data is protected using some mechanics that only allows ONE thread to act on it at a time.
Mistake # 6: Forgetting to release locks after a critical section
should use std::lock_guard which uses RAII style to manage the duration of mutex lock.
Mistake # 7: Not keeping critical sections as compact and small as possible
Mistake # 8 : Not acquiring multiple locks in the same order
This is one of the most common causes of DEADLOCK
Mistake # 10: Using mutexes when std::atomic types will suffice
When you have simple data types that needs to be updated, for example, a simple bool or a integer counter, using std:atomic will almost yield better performance than using a mutex.
Mistake # 11: Creating and Destroying a lot of threads directly when using a thread pool is available
Two of the most popular libraries that implements thread pools are Intel Thread Building Blocks(TBB) and Microsoft Parallel Patterns Library(PPL).
Mistake # 12: Not handling exceptions in background threads
Exceptions thrown in one thread cannot be caught in another thread
Mistake # 13: Using threads to simulate Asyn jobs when std::async will do
If you just need some code executed asynchronously i.e. without blocking execution of Main thread, your best bet is to use the std::async functionality to execute the code.
Mistake # 14: Not using std::launch::async if asynchronicity is desired
std::async is a bit of a misnomer because the function in it's default form may not execute in an asynchronous way !
Mistake # 15: Calling .Get() on a std::future in a time sensitive code path
Mistake # 16: Not realizing that an exception thrown inside an async task is propagated when std::future::get() is invoked.
Mistake # 17: Using std::async when you need granular control over thread execution
Mistake # 18: Creating many more "Runnable" threads than available cores
Mistake # 19: Using "volatile" keyword for synchronization
The "volatile" keyword in front of a variable type declaration does not make the operations on that variable atomic or thread safe in any way. What you probably want is an std::atomic.
Mistake # 20: Using a Lock Free architecture unless absolutely needed
No comments:
Post a Comment