I am writing a multithreaded program and have a function that will be called from multiple threads that is a static free function within a cpp file. This function will never be called from outside of the cpp file so I wanted to make it static so that it had internal linkage.
Googling around I found a lot of people saying "static functions are not thread safe" but then when I go to read up about it everyone seems to be talking about static member functions, not static free functions.
Are static free functions thread safe (assuming they don't access any shared state between threads)?
Any function that accesses no shared state is inherently thread safe. You only get a data race when you have unprotected read/writes to shared state. If there is no shared state, you can't have a data race.
This is why purely functional languages are naturally thread safe. If a function doesn't have side effects, then you can call it in as many threads as you want.
Static functions are the same as other functions. It is not the function, it is what the function does.
I think some people are mixing between terms. static function vs function with static variables.
while static function may be safe or not, a function with static variables is not safe without synchronization.
An example of such a function is strtok which keeps in a static variable the continuation point. when several threads use the old strtok, it may cause a mixture between the inputs.
Related
I've seen most examples using std::mutex where the mutex is global. I was wondering is there any specific reason why this is done? I've had programs of my own where I don't do this, and simply pass the mutex in as a std::thread std::ref. Isn't it bad practice to have globals, what is the rational behind global std::mutexes in C++ if there is no language restricting reason to do this?
It's bad practice to have globals except when it isn't. For example, std::cin is global.
Mutexes are in a sense global, regardless of how you make them available. They're shared between disparate pieces of code. So you can make them globals, or you can pass them down the call chain, through functions that don't use them, until you eventually reach someone who does. That's known as "tramp data" and it's also "bad practice". Choose your poison.
Most likely this was done to make the example easier to follow, allowing the use of the mutex itself to be the focus of the example rather than the exact specifics.
Typically a mutex protects a resource and in many cases it makes sense for the mutex to live alongside the resource. For example if you have a class with a member container that needs to be protected by a mutex, make the mutex also a member of the class. Then as the class instance is acted on by multiple threads the member-mutex can be used to protect the needed accesses to the internal container.
I have a C++ class with a static function:
class Foo
{
public:
static void bar(int &a)
{
a++;
}
}
EDIT:
The variable passed as argument is only used within the calling scope. So it is not accessed by another thread.
Do i have to use a mutex when i call this function from a seperate thread?
Thanks.
Calling this function requires only thread-local resources, the stack of thread. Therefore the answer is no. If the int variable is accessible by more than the calling thread, you will need a mutex for the variable
Whether a function is static has no bearing on whether calls to it need to be synchronised.
The determining factor is whether the function is re-entrant, and what you do with the data. In this case, the function is re-entrant (as it has no non-local state of its own, or in fact any state at all), and the data is owned/managed by the calling scope, so you will have to decide within the calling scope whether that integer requires protection.
But this is true whether bar is a static member, a non-static member, a free function, a macro, a cat, a black hole, or Jon Skeet's tumble dryer.
I'd like to mention that mutex is not the only thread synchronization primitive available, and in some scenarios far from most approriate one.
Provided synchronization is needed (see two other answers on why it might be needed depending on usage) don't jump into mutex world. For something as straitghtforward as a counter (this is what I see in the code) atomic variables (or, in absence of those, atomic operations on non-atomic types) often provide a better performance and more straightforward code.
In this particular case, incrementing a variable can be easily done in thread-safe way with following C++11 code:
static void bar(std::atomic<int>& a)
{
a.fetch_add(1, std::memory_order_relaxed);
}
memory_order_relaxed used here is really far-fetched, and not neccessarily applicable (however, often good for counters). Used here mostly for the example.
Like the title says:
If I have a class with a static member function, which by itself contains no static variables, can I consider the member function reentrant?
Static member functions are no different from namespace-scope functions (or even member functions) with respect to reentrancy. They are not predisposed either way, it depends entirely on what the function does inside.
The rules for Reentrancy laid out in the Wikipedia article on Reentrancy are as follows:
Reentrant code may not hold any static (or global) non-constant data.
Reentrant code may not modify its own code.
Reentrant code may not call non-reentrant computer programs or routines.
so as long as the member function follows those rules it should be ok.
The article Use reentrant functions for safer signal handling I feel gives a slightly better desciption:
A reentrant function is one that can be used by more than one task
concurrently without fear of data corruption. Conversely, a
non-reentrant function is one that cannot be shared by more than one
task unless mutual exclusion to the function is ensured either by
using a semaphore or by disabling interrupts during critical sections
of code. A reentrant function can be interrupted at any time and
resumed at a later time without loss of data. Reentrant functions
either use local variables or protect their data when global variables
are used.
A reentrant function:
Does not hold static data over successive calls
Does not return a pointer to static data; all data is provided by the caller of the function
Uses local data or ensures protection of global data by making a local copy of it
Must not call any non-reentrant functions
and then goes on to explain how this differs from thread-safety before going the article fully.
If your static member function contains only auto variables you could consider it re-entrant.
I have the following sample C++ code:
class Factory
{
public:
static Factory& createInstance()
{
static Factory fac;
return fac;
}
private:
Factory()
{
//Does something non-trivial
}
};
Let's assume that createInstance is called by two threads at the same time. So will the resulting object be created properly? What happens if the second thread enters the createInstance call when the first thread is in the constructor of Factory?
C++11 and above: local static creation is thread-safe.
The standard guarantees that:
The creation is synchronized.
Should the creation throws an exception, the next time the flow of execution passes the variable definition point, creation will be attempted again.
It is generally implemented with double-checking:
first a thread-local flag is checked, and if set, then the variable is accessed.
if not yet set, then a more expensive synchronized path is taken, and if the variable is created afterward, the thread-local flag is set.
C++03 and C++98: the standard knows no thread.
There are no threads as far as the Standard is concerned, and therefore there is no provision in the Standard regarding synchronization across threads.
However some compilers implement more than the standard mandates, either in the form of extensions or by giving stronger guarantees, so check out for the compilers you're interested in. If they are good quality ones, chances are that they will guarantee it.
Finally, it might not be necessary for it to be thread-safe. If you call this method before creating any thread, then you ensures that it will be correctly initialized before the real multi-threading comes into play, and you'll neatly side-step the issue.
Looking at this page, I'd say that this is not thread-safe, because the constructor could get called multiple times before the variable is finally assigned. An InterlockedCompareExchange() might be needed, where you create a local copy of the variable, then atomically assign the pointer to a static field via the interlocked function, if the static variable is null.
Of course it's thread safe! Unless you are a complete lunatic and spawn threads from constructors of static objects, you won't have any threads until after main() is called, and the createInstance method is just returning a reference to an already constructed object, there's no way this can fail. ISO C++ guarantees that the object will be constructed before the first use after main() is called: there's no assurance that will be before main is called, but is has to be before the first use, and so all systems will perform the initialisation before main() is called. Of course ISO C++ doesn't define behaviour in the presence of threads or dynamic loading, but all compilers for host level machines provide this support and will try to preserve the semantics specified for singly threaded statically linked code where possible.
The instantiation (first call) itself is threadsafe.
However, subsequent access will not be, in general. For instance, suppose after instantiation, one thread calls a mutable Factory method and another calls some accessor method in Factory, then you will be in trouble.
For example, if your factory keeps a count of the number of instances created, you will be in trouble without some kind of mutex around that variable.
However, if Factory is truly a class with no state (no member variables), then you will be okay.
I am pretty sure these classes are not thread safe.
But, is it safe to use different objects from these classes in different threads?
Do they have any global dependencies with each other like static data or anything to watch out for?
As long as the calls you are making are to static functions that do not access shared memory (shared between threads).
Basically the only time you will hit a problem is if the function you call accesses shared data. If your function simply does some work on data you provide it is thread safe.