- Back to Home »
- Thread Safety
Posted by : Sushanth
Tuesday, 15 December 2015
Thread Safety
• Thread safety
• How to use locks to ensure thread safety
• Semaphores and condition variables
• Atomic variables
• Thread-specific data
• Recommendations
• Knowledge checks
• Summary
Thread safety :
Thread safety refers to ensuring that modifications to shared memory are synchronized properly. This is critical because, although all threads have their own specific memory, all threads also have access to global shared memory.
Examples of shared memory include:
• Heap memory
• Function scope statics
• File scope statics
• Class scope statics
• Non-static global variables
The essence of thread safety is to ensure a correct program behavior regardless of what order the threads execute.
A race condition refers to a situation where program behavior is dependent on the order in which threads are executed (this is bad).
Examples of race conditions include:
• Multiple threads writing to the same memory location with no synchronization to enforce a specific order of operations.
• One thread writing to memory and another thread reading from the same memory location with no synchronization to enforce a specific order of operations.
Example:
A manufacturing assembly line maintains a running count of items completed, with separate controllers responsible for counting each kind of object.
In a multithreaded system, a race condition can arise because the controllers read and write a shared piece of data: the count.
Many interleavings will result in correct counts but – critically – some do not.
•
Thread-safe APIs in the standard C++ library
For a full list of thread-safe STL headers, visit the Ensuring thread safety (C++) page in the IBM info center.
• Thread safety implies that multiple threads can read from the same object.
• If any modifications are performed, however, it is the application’s responsibility to properly synchronize or lock where necessary.
Additional guidelines on thread safety can also be found on the Writing reentrant and threadsafe code page i.
• In particular, strtok() is not thread safe; you need to use strtok_r instead.
• Similarly, ctime() is not thread safe.
How to use locks to ensure thread safety
Locks:
In order to ensure thread safety, we can utilize “locking” APIs. Locking is simply a way to ensure that only one thread is allowed to execute a particular piece of code at a given time.
Locking example :
The figure shown here uses a database to illustrate locking variables. The database is tracking seats to be sold. The figure shows lots of people making queries. As long as they are just queries, multiple threads can access the variables safely because no changes are being made.
We can let multiple threads read the variable (seats) at the same time but, to keep the database accurate and complete, we need to lock as soon as we allow modifications to the database. To allow us to write that a seat has been sold, we make sure that the critical section of code between the yellow bars is locked by a thread. This way, only one thread can operate on that data until that thread is finished.
Locking performance issues:
Although locks can be used to guarantee thread safety, this safety comes at a performance cost. For example, if you lock everything that you do and you have 100 threads working, then while the lock is in place, 99 of the threads cannot work on any locked section of code.
Remember: The less you lock, the fewer threads you will have waiting as a result of the lock.
• Thread safety
• How to use locks to ensure thread safety
• Semaphores and condition variables
• Atomic variables
• Thread-specific data
• Recommendations
• Knowledge checks
• Summary
Thread safety :
Thread safety refers to ensuring that modifications to shared memory are synchronized properly. This is critical because, although all threads have their own specific memory, all threads also have access to global shared memory.
Examples of shared memory include:
• Heap memory
• Function scope statics
• File scope statics
• Class scope statics
• Non-static global variables
The essence of thread safety is to ensure a correct program behavior regardless of what order the threads execute.
A race condition refers to a situation where program behavior is dependent on the order in which threads are executed (this is bad).
Examples of race conditions include:
• Multiple threads writing to the same memory location with no synchronization to enforce a specific order of operations.
• One thread writing to memory and another thread reading from the same memory location with no synchronization to enforce a specific order of operations.
Example:
A manufacturing assembly line maintains a running count of items completed, with separate controllers responsible for counting each kind of object.
In a multithreaded system, a race condition can arise because the controllers read and write a shared piece of data: the count.
Many interleavings will result in correct counts but – critically – some do not.
•
Thread-safe APIs in the standard C++ library
For a full list of thread-safe STL headers, visit the Ensuring thread safety (C++) page in the IBM info center.
• Thread safety implies that multiple threads can read from the same object.
• If any modifications are performed, however, it is the application’s responsibility to properly synchronize or lock where necessary.
Additional guidelines on thread safety can also be found on the Writing reentrant and threadsafe code page i.
• In particular, strtok() is not thread safe; you need to use strtok_r instead.
• Similarly, ctime() is not thread safe.
How to use locks to ensure thread safety
Locks:
In order to ensure thread safety, we can utilize “locking” APIs. Locking is simply a way to ensure that only one thread is allowed to execute a particular piece of code at a given time.
Locking example :
The figure shown here uses a database to illustrate locking variables. The database is tracking seats to be sold. The figure shows lots of people making queries. As long as they are just queries, multiple threads can access the variables safely because no changes are being made.
We can let multiple threads read the variable (seats) at the same time but, to keep the database accurate and complete, we need to lock as soon as we allow modifications to the database. To allow us to write that a seat has been sold, we make sure that the critical section of code between the yellow bars is locked by a thread. This way, only one thread can operate on that data until that thread is finished.
Locking performance issues:
Although locks can be used to guarantee thread safety, this safety comes at a performance cost. For example, if you lock everything that you do and you have 100 threads working, then while the lock is in place, 99 of the threads cannot work on any locked section of code.
Remember: The less you lock, the fewer threads you will have waiting as a result of the lock.