Given the following code, Is it guaranteed to see the latest value 4 of a ?
int a;
mutex mtx;
void f() {
unique_lock<mutex> lck(mtx);
// read(a);
// is it guarantee it will see the value 4?
}
int main() {
a = 4;
thread(f);
}
Yes, it is guaranteed:
32.4.2.2 Constructors [thread.thread.constr]
Synchronization: The completion of the invocation of the constructor
synchronizes with the beginning of the invocation of the copy of f.
In other words, the construction of std::thread itself, which occurs in the original execution thread, synchronizes with the beginning of the invocation of the thread function. Or, in other words: everything that happens before std::thread gets constructed, in the original thread, is visible in the thread function.
Related
I have the following scenario:
void thread_func(const Widget& w) { /*does something here...*/ }
int main() {
Widget w{ /* some arguments */ };
std::thread t(thread_func, std::move(w));
t.detach();
// lots of other stuff down here ...
}
Now I know that temporary objects, when bound to const T& parameters in a function call have their lifetime extended until the completion of the expression in which the call occurs. But in this multithreaded context, does the "completion of the expression in which the call occurs" refer to the construction of t, or to the completion of thread_func, since thread_func is (at the very least, conceptually) called at the end of t's constructor?
In a scenario with a single thread the answer is clear:
Widget h() { return Widget{/* some arguments */}; }
void g(const Widget& x) { /* do something */ }
void f() {
g(h());
}
the lifetime of the temporary within the call to g lives until g has finished executing, since execution pauses within f, begins in g, and only resumes in f once g has finished executing. In a multithreaded environment, the answer is more confusing to me because construction happens in a single thread, but the execution directly following construction happens concurrently.
This is not a lifetime extension situation. All temporaries live until then end of the full-expression, i.e. the outermost ;.
std::thread t(thread_func, std::move(w)); - this is a full-expression. So yes, the thread is starting when the expression is already ended.
Your thread is started with a reference to the original object, which must be keep alive for as long as it's needed in the thread.
Bonus notes:
You can't move into an lvalue-reference. Your std::move has no effect. But even if you changed the function to accept an rvalue reference, it would not change the fact that the original object needs to be kept alive externally. Remember that std::move does not move anything. What would change it though is if you simply accepted it by value.
void thread_func(Widget w) { /*does something here...*/ }
Detaching a thread is almost never needed. In your example the program will end when the main thread finishes, it will not wait for any other thread to finish. Consider joining your thread before main() returns instead.
I have below code where function bar lock the mutex and then called function foo, however function foo lock the same mutex. according to my understanding, dead-lock will take place because foo are trying to lock the same mutex and it has been locked in function bar. But below code executes without any halt. Who knows the reason??
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void foo()
{
pthread_mutex_lock(&mutex);
cout<<"excuting foo!!"<<endl;
pthread_mutex_unlock(&mutex);
}
void bar()
{
pthread_mutex_lock(&mutex);
cout<<"excuting bar!!"<<endl;
foo();
pthread_mutex_unlock(&mutex);
}
int main()
{
bar();
}
The POSIX thread specification allows a POSIX thread implementation to use any of the standard three mutex types as the default one:
If the mutex type is PTHREAD_MUTEX_DEFAULT, the behavior of
pthread_mutex_lock() may correspond to one of the three other standard
mutex types
What is PTHREAD_MUTEX_DEFAULT? That's pretty much what you expect:
The default value of the type attribute is PTHREAD_MUTEX_DEFAULT.
...
An implementation may map PTHREAD_MUTEX_DEFAULT to one of the other
mutex types.
You are expecting your mutex to be PTHREAD_MUTEX_NORMAL which will cause a deadlock here. However, your particular thread implementation appears to be the PTHREAD_MUTEX_RECURSIVE type, which can be locked more than once by the same process. This is the behavior you are observing.
You need to modify bar() as:
void bar()
{
pthread_mutex_lock(&mutex);
cout<<"excuting bar!!"<<endl;
pthread_mutex_unlock(&mutex);
foo();
}
In your code, deadlock is there because sequence is following
1. bar () locks mutex,
2. Foo() trying to lock mutex again which is already locked by bar
3. bar() unlocks it,but earlier operation step 2, still waiting for mutex. This steps waits for step 2 to finish
Please consider the following code:
void h(M m2)
{
...
}
int main()
{
while (true) {
M m1 = ...;
std::thread t(h, std::move(m1));
t.detach();
}
}
Is it guaranteed that m2 is properly move-d constructed from m1 before m1 is destroyed? Or is there a race?
The standard seems clear to me:
Effects: Constructs an object of type thread. The new thread of execution executes INVOKE (DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) with the calls to
DECAY_COPY being evaluated in the constructing thread.
Since the copy is made in the calling thread it must complete before the constructor invocation returns.
Construction of m2 is done from a different object (the result of the DECAY_COPY), not from m1, so it doesn't matter whether m1 has been destroyed or not.
The result of the DECAY_COPY must be stored somewhere by the implementation so that it doesn't go out of scope until the target function has been initialized, but that is the implementation's job to get right. Destruction of m1 doesn't have any effect on it.
I wonder if this code is fine or not:
#include <iostream>
#include <future>
struct Foo
{
Foo()
:m_a(0)
{
}
int m_a;
};
int main()
{
Foo f;
auto handle =
std::async( std::launch::async,
[](Foo* f) { std::cout << f->m_a << '\n'; } ,
&f
);
handle.get();
}
I believe m_a should be protected by a synchronization mechanism but my colleague says it is not necessary.
EDIT: To clarify my question: I am worried that the STORE operation from the constructor of Foo() happens after the LOAD operation from the other thread. I can't see what mechanism prevents the compiler from executing those instruction in this order.
EDIT: I believe an enthusiastic compiler could decide to inline the constructor, and delay the STORE operation for after the CALL operation to std::async. In which case the second thread could access m_a before it has been committed to memory.
Yes, this is correctly synchronised.
From the specification for async, C++11 30.6.8/5:
the invocation of async synchronizes with the invocation of f.
where f is the function argument to async (the lambda in your example).
Initialisation of f.m_a is sequenced before the call to async, and therefore before any access by the asynchronous function.
Furthermore,
the completion of the function f is sequenced before the shared state is made ready.
so the access must happen before the call to get() returns, and therefore before the object is destroyed.
I want to initialize a field in a constructor and never change it afterwards. I want the guarantee that after the constructor finished, every read of the field reads the initialized value, no matter in which thread the read happens.
Basically, I want the same guarantees as a final field gives in Java.
This is what I tried:
#include <atomic>
#include <iostream>
#include <thread>
struct Foo
{
Foo(int x) : x(x)
{
// ensure all writes are visible to other threads
std::atomic_thread_fence(std::memory_order_release);
}
int x;
};
void print_x(Foo const& foo)
{
// I don't think I need an aquire fence here, because the object is
// newly constructed, so there cannot be any stale reads.
std::cout << foo.x << std::endl;
}
int main()
{
Foo foo(1);
std::thread t(print_x, foo);
t.join();
}
Is this guaranteed to always print 1 or can thread t observe foo.x in an uninitialized state?
What if instead of using the member initializer x(x) an explicit assignment this->x = x; is used?
What if x is not an int but some class type?
Does making x a const int change anything with regards to thread safety?
Basically, if everything else is correct, there shouldn't be any
problem. After initializing the field, and before accessing it
in any thread, you need some sort of memory synchronization;
that's clear. Otherwise, how can the other threads know that it
is constructed. If you initialize it before starting the other
threads, then creating the threads will ensure the necessary
synchronization. (This only holds between the thread doing the
creation, and the created thread. Other already running threads
are not synchronization.) After that, as long as no thread
modifies the value, no synchronization is needed.
With regards to your code, you don't need the fence, because the
value is initialized before any of the other threads are
created, and creating the thread ensures the necessary
synchronization.