Threading and un-safe variables - multithreading

I have code listed here: Threading and Sockets.
The answer to that question was to modify isListening with volatile. As I remarked, that modifier allowed me to access the variable from another thread. After reading MSDN, I realized that I was reading isListening from the following newly created thread process.
So, my questions now:
Is volatile the preferred method,since I am basically making a non-thread safe request on a variable? I have read about the Interlocked class and wondered if this was something that would be better to use in my code. Interlocked looks similar to what lock(myObj) is doing - but with a little more 'flair' and control. I do know that simply applying a lock(myObj) code block around isListening did not work.
Should I implement the Interlocked class?
Thank you for your time and responses.

If all you are doing is reading and writing a variable across multiple threads in C#, then you do not have to worry about synchronizing access to (locking) that variable providing its type is bool, char, byte, sbyte, short, ushort, int, uint, float, and reference types. See here for details.
In the example from your other post, the reason you have to mark the field as volatile is to ensure that it is not subject to compiler optimizations and that the most current value is present in the field at all times. See here for details on the volatile keyword. Doing this allows that field to be read and written across threads without having to lock (synchronize access to) it. But keep in mind, the volatile keyword can only be used for your field because it is of type bool. Had it been a double, for example, the volatile keyword wouldn't work, and you'd have to use a lock.
The Interlocked class is used for a specialized purpose, namely incrementing, decrementing, and exchanging values of (typically) numeric types. These operations are not atomic. For example, if you are incrementing a value in one thread and trying to read the resulting value in another thread, you would normally have to lock the variable to prevent reading intermediate results. The Interlocked class simply provides some convenience functions so you don't have to lock the variable yourself while the increment operation is performed.
What you are doing with the isListening flag does not require use of the Interlocked class. Marking the field as volatile is sufficient.

Edit due to lunchtime rushed answer..
The lock statement used in your previous code is locking an object instance that is created in the scope of a method so it will have no effect on another thread calling into the same method. Each thread must be able to lock the same instance of an object in order to synchronise access to the given block of code. One way to do this (depending on the semantics you require) is to make the locking object a private static variable of the class that it is used in. This will allow multiple instances of a given object to synchronise access to a block of code or a single shared resource. If synchronisation is required for individual instances of an object or a resource that is instance specific then static should be emitted.
Volatile doesn't guarantee that reads or writes to the given variable will be atomic amongst different threads. It is a compiler hint to preserve ordering of instructions and prevents the variable from being cached inside a register. In general unless you are working on something extremely performance sensitive (low locking / lock free algorithms, data structures etc.) or really know you are doing then I would opt for using Interlocked. The performance difference between using volatile / interlocked / lock in most applications will be neglible, so if you are unsure its best to use what ever gives you the safest guarantee (read Joe Duffy's blog & book).
For example using volatile in the example below is not thread safe and the incremented counter does not reach 10,000,000 (when I ran the test it reached 8848450) . This is because volatile only guarentees reading the latest value (e.g. not cached from a register for example). When using interlocked the operation is thread safe and the counter does reach 10,000,000.
public class Incrementor
{
private volatile int count;
public int Count
{
get { return count; }
}
public void UnsafeIncrement()
{
count++;
}
public void SafeIncrement()
{
Interlocked.Increment(ref count);
}
}
[TestFixture]
public class ThreadingTest
{
private const int fiveMillion = 5000000;
private const int tenMillion = 10000000;
[Test]
public void UnsafeCountShouldNotCountToTenMillion()
{
const int iterations = fiveMillion;
Incrementor incrementor = new Incrementor();
Thread thread1 = new Thread(() => UnsafeIncrement(incrementor, iterations));
Thread thread2 = new Thread(() => UnsafeIncrement(incrementor, iterations));
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Assert.AreEqual(tenMillion, incrementor.Count);
}
[Test]
public void SafeIncrementShouldCountToTenMillion()
{
const int iterations = fiveMillion;
Incrementor incrementor = new Incrementor();
Thread thread1 = new Thread(() => SafeIncrement(incrementor, iterations));
Thread thread2 = new Thread(() => SafeIncrement(incrementor, iterations));
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Assert.AreEqual(tenMillion, incrementor.Count);
}
private void UnsafeIncrement(Incrementor incrementor, int times)
{
for (int i =0; i < times; ++i)
incrementor.UnsafeIncrement();
}
private void SafeIncrement(Incrementor incrementor, int times)
{
for (int i = 0; i < times; ++i)
incrementor.SafeIncrement();
}
}
If you search for 'interlocked volatile' you will find a number of answers to your question. The one below for example addresses your question:
A simple example below shows
Volatile vs. Interlocked vs. lock

"One way to do this is to make the locking object a private static variable of the class that it is used in."
Why should it be static? You can access the same function from multiple threads as long as they work on different object. I am not saying that it would not work, but would seriously slow the speed of the application without any advantages. Or am I missing something?
And here is what MSDN says about volatiles:
"Also, when optimizing, the compiler must maintain ordering among references to volatile objects as well as references to other global objects. In particular,
A write to a volatile object (volatile write) has Release semantics; a reference to a global or static object that occurs before a write to a volatile object in the instruction sequence will occur before that volatile write in the compiled binary.
A read of a volatile object (volatile read) has Acquire semantics; a reference to a global or static object that occurs after a read of volatile memory in the instruction sequence will occur after that volatile read in the compiled binary.
This allows volatile objects to be used for memory locks and releases in multithreaded applications."

Related

Give me a scenario where such an output could happen when multi-threading is happening

Just trying to understand threads and race condition and how they affect the expected output. In the below code, i once had an output that began with
"2 Thread-1" then "1 Thread-0" .... How could such an output happen? What I understand is as follows:
Step1:Assuming Thread 0 started, it incremented counter to 1,
Step2: Before printing it, Thread 1 incremented it to 2 and printed it,
Step3: Thread 0 prints counter which should be 2 but is printing 1.
How could Thread 0 print counter as 1 when Thread 1 already incremented it to 2?
P.S: I know that synchronized key could deal with such race conditions, but I just want to have some concepts done before.
public class Counter {
static int count=0;
public void add(int value) {
count=count+value;
System.out.println(count+" "+ Thread.currentThread().getName());
}
}
public class CounterThread extends Thread {
Counter counter;
public CounterThread(Counter c) {
counter=c;
}
public void run() {
for(int i=0;i<5;i++) {
counter.add(1);
}
}
}
public class Main {
public static void main(String args[]) {
Counter counter= new Counter();
Thread t1= new CounterThread(counter);
Thread t2= new CounterThread(counter);
t1.start();
t2.start();
}
}
How could Thread 0 print counter as 1 when Thread 1 already incremented it to 2?
There's a lot more going on in these two lines than meets the eye:
count=count+value;
System.out.println(count+" "+ Thread.currentThread().getName());
First of all, the compiler doesn't know anything about threads. It's job is to emit code that will achieve the same end result when executed in a single thread. That is, when all is said and done, the count must be incremented, and the message must be printed.
The compiler has a lot of freedom to re-order operations, and to store values in temporary registers in order to ensure that the correct end result is achieved in the most efficient way possible. So, for example, the count in the expression count+" "+... will not necessarily cause the compiler to fetch the latest value of the global count variable. In fact it probably will not fetch from the global variable because it knows that the result of the + operation still is sitting in a CPU register. And, since it doesn't acknowledge that other threads could exist, then it knows that there's no way that the value in the register could be any different from what it stored into the global variable after doing the +.
Second of all, the hardware itself is allowed to stash values in temporary places and re-order operations for efficiency, and it too is allowed to assume that there are no other threads. So, even when the compiler emits code that says to actually fetch from or store to the global variable instead of to or from a register, the hardware does not necessarily store to or fetch from the actual address in memory.
Assuming your code example is Java code, then all of that changes when you make appropriate use of synchronized blocks. If you would add synchronized to the declaration of your add method for example:
public synchronized void add(int value) {
count=count+value;
System.out.println(count+" "+ Thread.currentThread().getName());
}
That forces the compiler to acknowledge the existence of other threads, and the compiler will emit instructions that force the hardware to acknowledge other threads as well.
By adding synchronized to the add method, you force the hardware to deliver the actual value of the global variable on entry to the method, your force it to actually write the global by the time the method returns, and you prevent more than one thread from being in the method at the same time.

Accessing an atomic member of a class held by a shared_ptr

I'm trying to create a small class that will allow me to facilitate a communication between two threads.
Those threads most probably will outlive the context in which the above mentioned class was created as they are queued onto a thread pool.
What I have tried so far (on coliru as well):
class A
{
public:
A(int maxVal) : maxValue(maxVal) {}
bool IsOverMax() const { return cur >= maxValue; }
void Increase() { cur++; }
private:
const int maxValue;
atomic_int cur{ 0 };
};
possible usage:
void checking(const shared_ptr<A> counter)
{
while(!counter->IsOverMax())
{
cout<<"Working\n"; // do work
std::this_thread::sleep_for(10ms);
}
}
void counting(shared_ptr<A> counter)
{
while (!counter->IsOverMax())
{
cout<<"Counting\n";
counter->Increase(); // does this fall under `...uses a non-const member function of shared_ptr then a data race will occur`? http://en.cppreference.com/w/cpp/memory/shared_ptr/atomic
std::this_thread::sleep_for(9ms);
}
}
int main()
{
unique_ptr<thread> t1Ptr;
unique_ptr<thread> t2Ptr;
{
auto aPtr = make_shared<A>(100); // This might be out of scope before t1 and t2 end
t1Ptr.reset(new thread(checking, aPtr)); // To simbolize that t1,t2 will outlive the scope in which aPtr was originaly created
t2Ptr.reset(new thread(counting, aPtr));
}
t2Ptr->join();
t1Ptr->join();
//cout<< aPtr->IsOverMax();
}
The reason I'm concerned is that the documentation says that:
If multiple threads of execution access the same std::shared_ptr object without synchronization and any of those accesses uses a non-const member function of shared_ptr then a data race will occur unless all such access is performed through these functions, which are overloads of the corresponding atomic access functions (std::atomic_load, std::atomic_store, etc.)
So Increase is a non const function, are the copies of aPtr are the same std::shared_ptr for this context or not ?
Is this code thread-safe?
Would this be OK for a non atomic object (say using an std::mutex to lock around reads and writes to a regular int)?
In any case why?
So Increase is a non const function, are the copies of aPtr are the same std::shared_ptr for this context or not ?
At std::thread creation, aPtr is passed by value. Therefore, it is guaranteed that:
You don't introduce a data race since each thread gets its own instance of shared_ptr (although they manage the same object A).
The documentation you are referring to describes a scenario whereby multiple threads operate on the same shared_ptr instance.
In that case, only const member functions can be called (see below), or synchronization is required.
shared_ptr reference-count is incremented before aPtr goes out of scope in main
So yes, this is a correct way to use shared_ptr.
Is this code thread-safe?
Your code does not introduce a data race, neither with access to shared_ptr instances, nor with access to the managed object A.
This means that there are no conflicting, non-atomic, read and write operations to the same memory location performed by multiple threads.
However, keep in mind that, in checking(), the call to IsOverMax() is separated from the actual work that follows
(Increase() could be called by the second thread after IsOverMax() but before 'do work'). Therefore, you could 'do work' while cur has gone over its maximum.
Whether or not that is a problem depends on your specification, but it is called a race condition which is not necessarily a programming error (unlike a data race which causes undefined behavior).
Would this be OK for a non atomic object (say using an std::mutex to lock around reads and writes to a regular int)?
cur can be a regular int (non-atomic) if you protect it with a std::mutex. The mutex must be locked for both write and read access in order to prevent a data race.
One remark on calling const member functions on objects shared by multiple threads.
The use of const alone does not guarantee that no data race is introduced.
In this case, the guarantee applies to shared_ptr const member functions, because the documentation says so.
I cannot find in the C++ standard whether that guarantee applies to all const member functions in the Standard Library
That documentation is talking about the member functions of shared_ptr, not the member functions of your class. Copies of shared_ptr objects are different objects.
I believe the code is thread safe, because the only changing variable written and read on different threads is cur, and that variable is atomic.
If cur was not atomic and access to it in both Increase() and IsOverMax() was protected by locking a std::mutex, that code would also be thread safe.

If 2 threads running together, will it coflicts global variable value

If 2 threads running together then how global variable will be updated by both threads. Is that value will be conflicted?
This would depend entirely on what you are doing with the global variable being accessed by multiple threads.
Unless the global variable is thread-safe, in the sense that the variable is locked during an operation to change it's value, then it seems likely that you could end up with a race condition occurring.
I am not certain which language you are working with, but it may make sense to create an accessor for the variable (such as a property) which is locked whilst changes are being applied. In C# you could accomplish this easily with the following pseudo-code as an example:
private object _LockObject = new object();
private int _SomeProperty;
public int SomeProperty
{
get { return _SomeProperty; }
set
{
lock (_LockObject)
{
_SomeProperty = value;
}
}
}
The lock ensuring that the code to change the value of the variable is thread-safe (because it is locked during each update operation).

Why would we want to make a function recursive when it has a mutex lock?

https://stackoverflow.com/a/5524120/462608
If you want to call functions recursively, which lock the same mutex, then they either
have to use one recursive mutex, or
have to unlock and lock the same non-recursive mutex again and again (beware of concurrent threads!), or
have to somehow annotate which mutexes they already locked (simulating recursive ownership/mutexes).
Can in any case this be a "sensible" design decision to make function recursive which already has a mutex lock?
Well, one possibility is that the resource you're using lends itself naturally to recursive algorithms.
Think of searching a binary tree, while preventing everyone else from using (especially modifying) the tree out with a mutex.
If you use a recursive mutex, you can simply have one function search() that you pass the root node in to. It then recursively calls itself as per a normal binary tree search but the first thing it does in that function is to lock the mutex (while this looks like Python, that's really just because Python is an ideal basis for pseudo-code):
def search (haystack, mutex, needle):
lock mutex recursively
if haystack == NULL:
unlock mutex and return NULL
if haystack.payload == needle:
unlock mutex and return haystack
if haystack.payload > needle:
found = search (haystack.left, mutex, needle)
else:
found = search (haystack.right, mutex, needle)
unlock mutex and return found
The alternative is to separate the mutex lock and search into two separate functions like search() (public) and search_while_locked() (most likely private):
def private search_while_locked (haystack, needle):
if haystack == NULL:
return NULL
if haystack.payload == needle:
return haystack
if haystack.payload > needle:
return search_while_locked (haystack.left, needle)
return search_while_locked (haystack.right, needle)
def search (haystack, mutex, needle):
lock mutex non-recursively
found = search_while_locked (haystack.right, needle)
unlock mutex and return found
While that sort of defeats the elegance of the recursive solution, I actually prefer it since it reduces the amount of work that needs to be done (however small that work is, it's still work).
And languages that lend themselves easily to public/private functions can encapsulate the details well. The user of your class has no knowledge (or need of knowledge) as to how you do things within your class, they just call the public API.
Your own functions, however, have access to all the non-public stuff as well as full knowledge as to what locks need to be in place for certain operations.
Another possibility is very much related to that but without being recursive.
Think of any useful operation you may want users to perform on your data which requires that no-one else be using it during that time. So far, you have just the classic case for a non-recursive mutex. For example, clearing all of the entries out of a queue:
def clearQueue():
lock mutex
while myQueue.first <> null:
myQueue.pop()
unlock mutex
Now let's say you find that rather useful and want to call it from your destructor, which already locks the mutex:
def destructor():
lock mutex
clearQueue()
doSomethingElseNeedingLock()
unlock mutex
Obviously, with a non-recursive mutex, that's going to lock up on the first line of clearQueue after your destructor calls it, which may be one reason why you'd want a recursive mutex.
You could use the afore-mentioned method of providing a locking public function and a non-locking private one:
def clearQueueLocked():
while myQueue.first <> null:
myQueue.pop()
def clearQueue():
lock mutex
clearQueueLocked():
unlock mutex
def destructor():
lock mutex
clearQueueLocked():
doSomethingElseNeedingLock()
unlock mutex and return
However, if there are a substantial number of these public/private function pairs, it may get a little messy.
In addition to paxdiablo's exmaple using an actual recursive funciotn, don't forget that using a mutex recursively doesn't necessarily mean that the functions involved are recursive. I've found use for recursive mutexes for dealing with a situation where you have complex operations which need to be atomic with respect to some data structure, with those complex operations rely on more fundamental operations that still need to use the mutex since the fundamental operations can be used on their own as well. An example might be something like the following (note that the code is illustrative only - it doesn't use proper error handling or transactional techniques that might really be necessary when dealing with accounts and logs):
struct account
{
mutex mux;
int balance;
// other important stuff...
FILE* transaction_log;
};
void write_timestamp( FILE*);
// "fundamental" operation to write to transaction log
void log_info( struct account* account, char* logmsg)
{
mutex_acquire( &account->mux);
write_timestamp( account->transaction_log);
fputs( logmsg, account->transaction_log);
mutex_release( &account->mux);
}
// "composed" operation that uses the fundamental operation.
// This relies on the mutex being recursive
void update_balance( struct account* account, int amount)
{
mutex_acquire( &account->mux);
int new_balance = account->balance + amount;
char msg[MAX_MSG_LEN];
snprintf( msg, sizeof(msg), "update_balance: %d, %d, %d", account->balance, amount, new_balance);
// the following call will acquire the mutex recursively
log_info( account, msg);
account->balance = new_balance;
mutex_release( &account->mux);
}
To do something more or less equivalent without recursive mutexes means that the code would need to take care not to reacquire the mutex if it already held it. One option is to add some sort of flag (or thread ID) to the data structure to indicate if the mutex is already held. In this case, you're essentially implementing recursive mutexes - a trickier bit of work than it might seem at first to get right. An alternative is to pass a flag indicating you already acquired the mutex to functions as a parameter (easier to implement and get right) or simply have even more fundamental operations that assume the mutex is already acquired and call those from the higher level functions that take on the responsibility of acquiring the mutex:
// "fundamental" operation to write to transaction log
// this version assumes that the lock is already held
static
void log_info_nolock( struct account* account, char* log msg)
{
write_timestamp( account->transaction_log);
fputs( logmsg, account->transaction_log);
}
// "public" version of the log_info() function that
// acquires the mutex
void log_info( struct account* account, char* logmsg)
{
mutex_acquire( &account->mux);
log_info_nolock( account, logmsg);
mutex_release( &account->mux);
}
// "composed operation that uses the fundamental operation
// since this function acquires the mutex, it much call the
// "nolock" version of the log_info() function
void update_balance( int amount)
{
mutex_acquire( &account->mux);
int new_balance = account->balance + amount;
char msg[MAX_MSG_LEN];
snprintf( msg, sizeof(msg), "update_balance: %d, %d, %d", account->balance, amount, new_balance);
// the following call assumes the lock is already acquired
log_info_nolock( account, msg);
account->balance = new_balance;
mutex_release( &account->mux);
}

Is there a way in c++11 to prevent "normal" operations from sliping before or after atomic operation

I'm interested in doing something like(single thread update, multiple threads read banneedURLs):
atomic<bannedURLList*> bannedURLs;//global variable pointing to the currently used instance of struct
void updateList()
{
//no need for mutex because only 1 thread updates
bannedURLList* newList= new bannedURLList();
bannedURLList* oldList=bannedURLs;
newList->initialize();
bannedURLs=newList;// line must be after previous line, because list must be initialized before it is ready to be used
//while refcnt on the oldList >0 wait, then delete oldList;
}
reader threads do something like this:
{
bannedURLs->refCnt++;
//use bannedURLs
bannedURLs->refCnt--;
}
struct memeber refCnt is also atomic integer
My question is how to prevent reordering of this 2 lines:
newList->initialize();
bannedURLs=newList;
Can it be done in std:: way?
Use bannedURLs.store(newList); instead of bannedURLs=newList;. Since you didn't pass a weak ordering specifier, this forces full ordering in the store.

Resources