Is it possible for 2 threads lock a mutex at the same time (use mutex wrapper)?
up vote
-2
down vote
favorite
The question comes from an exmaple of std::condition_variable
As far as I know, when I construct a new thread
, it starts to execute immediately.
So I wonder, would cv.wait(lk, {return ready;});
in worker_thread()
, and std::lock_guard<std::mutex> lk(m);
in main
, lock the mutex at the same time? Could this happen?
(From cppreference I know that std::condition_variable::wait
and std::lock_guard
would lock the mutex during the construction.)
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
void worker_thread()
{
// Wait until main() sends data
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, {return ready;});
// after the wait, we own the lock.
std::cout << "Worker thread is processing datan";
data += " after processing";
// Send data back to main()
processed = true;
std::cout << "Worker thread signals data processing completedn";
// Manual unlocking is done before notifying, to avoid waking up
// the waiting thread only to block again (see notify_one for details)
lk.unlock();
cv.notify_one();
}
int main()
{
std::thread worker(worker_thread);
data = "Example data";
// send data to the worker thread
{
std::lock_guard<std::mutex> lk(m);
ready = true;
std::cout << "main() signals data ready for processingn";
}
cv.notify_one();
// wait for the worker
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, {return processed;});
}
std::cout << "Back in main(), data = " << data << 'n';
worker.join();
}
c++
add a comment |
up vote
-2
down vote
favorite
The question comes from an exmaple of std::condition_variable
As far as I know, when I construct a new thread
, it starts to execute immediately.
So I wonder, would cv.wait(lk, {return ready;});
in worker_thread()
, and std::lock_guard<std::mutex> lk(m);
in main
, lock the mutex at the same time? Could this happen?
(From cppreference I know that std::condition_variable::wait
and std::lock_guard
would lock the mutex during the construction.)
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
void worker_thread()
{
// Wait until main() sends data
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, {return ready;});
// after the wait, we own the lock.
std::cout << "Worker thread is processing datan";
data += " after processing";
// Send data back to main()
processed = true;
std::cout << "Worker thread signals data processing completedn";
// Manual unlocking is done before notifying, to avoid waking up
// the waiting thread only to block again (see notify_one for details)
lk.unlock();
cv.notify_one();
}
int main()
{
std::thread worker(worker_thread);
data = "Example data";
// send data to the worker thread
{
std::lock_guard<std::mutex> lk(m);
ready = true;
std::cout << "main() signals data ready for processingn";
}
cv.notify_one();
// wait for the worker
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, {return processed;});
}
std::cout << "Back in main(), data = " << data << 'n';
worker.join();
}
c++
1
std::condition_variable::wait 1) __Atomically releases lock__, blocks the current executing thread, and adds it to the list of threads waiting on *this. The thread will be unblocked when notify_all() or notify_one() is executed. It may also be unblocked spuriously. When unblocked, regardless of the reason, lock is reacquired and wait exits. If this function exits via exception, lock is also reacquired.
– tkausl
Nov 11 at 7:04
add a comment |
up vote
-2
down vote
favorite
up vote
-2
down vote
favorite
The question comes from an exmaple of std::condition_variable
As far as I know, when I construct a new thread
, it starts to execute immediately.
So I wonder, would cv.wait(lk, {return ready;});
in worker_thread()
, and std::lock_guard<std::mutex> lk(m);
in main
, lock the mutex at the same time? Could this happen?
(From cppreference I know that std::condition_variable::wait
and std::lock_guard
would lock the mutex during the construction.)
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
void worker_thread()
{
// Wait until main() sends data
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, {return ready;});
// after the wait, we own the lock.
std::cout << "Worker thread is processing datan";
data += " after processing";
// Send data back to main()
processed = true;
std::cout << "Worker thread signals data processing completedn";
// Manual unlocking is done before notifying, to avoid waking up
// the waiting thread only to block again (see notify_one for details)
lk.unlock();
cv.notify_one();
}
int main()
{
std::thread worker(worker_thread);
data = "Example data";
// send data to the worker thread
{
std::lock_guard<std::mutex> lk(m);
ready = true;
std::cout << "main() signals data ready for processingn";
}
cv.notify_one();
// wait for the worker
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, {return processed;});
}
std::cout << "Back in main(), data = " << data << 'n';
worker.join();
}
c++
The question comes from an exmaple of std::condition_variable
As far as I know, when I construct a new thread
, it starts to execute immediately.
So I wonder, would cv.wait(lk, {return ready;});
in worker_thread()
, and std::lock_guard<std::mutex> lk(m);
in main
, lock the mutex at the same time? Could this happen?
(From cppreference I know that std::condition_variable::wait
and std::lock_guard
would lock the mutex during the construction.)
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
void worker_thread()
{
// Wait until main() sends data
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, {return ready;});
// after the wait, we own the lock.
std::cout << "Worker thread is processing datan";
data += " after processing";
// Send data back to main()
processed = true;
std::cout << "Worker thread signals data processing completedn";
// Manual unlocking is done before notifying, to avoid waking up
// the waiting thread only to block again (see notify_one for details)
lk.unlock();
cv.notify_one();
}
int main()
{
std::thread worker(worker_thread);
data = "Example data";
// send data to the worker thread
{
std::lock_guard<std::mutex> lk(m);
ready = true;
std::cout << "main() signals data ready for processingn";
}
cv.notify_one();
// wait for the worker
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, {return processed;});
}
std::cout << "Back in main(), data = " << data << 'n';
worker.join();
}
c++
c++
edited Nov 11 at 7:04
asked Nov 11 at 7:01
Rick
1,535929
1,535929
1
std::condition_variable::wait 1) __Atomically releases lock__, blocks the current executing thread, and adds it to the list of threads waiting on *this. The thread will be unblocked when notify_all() or notify_one() is executed. It may also be unblocked spuriously. When unblocked, regardless of the reason, lock is reacquired and wait exits. If this function exits via exception, lock is also reacquired.
– tkausl
Nov 11 at 7:04
add a comment |
1
std::condition_variable::wait 1) __Atomically releases lock__, blocks the current executing thread, and adds it to the list of threads waiting on *this. The thread will be unblocked when notify_all() or notify_one() is executed. It may also be unblocked spuriously. When unblocked, regardless of the reason, lock is reacquired and wait exits. If this function exits via exception, lock is also reacquired.
– tkausl
Nov 11 at 7:04
1
1
std::condition_variable::wait 1) __Atomically releases lock__, blocks the current executing thread, and adds it to the list of threads waiting on *this. The thread will be unblocked when notify_all() or notify_one() is executed. It may also be unblocked spuriously. When unblocked, regardless of the reason, lock is reacquired and wait exits. If this function exits via exception, lock is also reacquired.
– tkausl
Nov 11 at 7:04
std::condition_variable::wait 1) __Atomically releases lock__, blocks the current executing thread, and adds it to the list of threads waiting on *this. The thread will be unblocked when notify_all() or notify_one() is executed. It may also be unblocked spuriously. When unblocked, regardless of the reason, lock is reacquired and wait exits. If this function exits via exception, lock is also reacquired.
– tkausl
Nov 11 at 7:04
add a comment |
2 Answers
2
active
oldest
votes
up vote
3
down vote
accepted
Mutex are meant to get a lock on resource, only 1 thread can get that lock. Locking of mutex is atomic, 2 threads cannot acquire a lock on mutex, if they can, then it defeats the purpose of mutex locks!
Mutexes are built such that locking is an atomic operation: it will only complete on one thread at a time, regardless of how many threads are attempting to lock
add a comment |
up vote
1
down vote
"Mutex" is a contraction of "mutual exclusion"; it's purpose is to allow only one thread to lock the mutex at any time.
That said, there's a serious problem in that example. It has a potential deadlock, because it tries too hard to sequence inherently non-sequential operations.
The problem occurs if main
goes through its locking code, sets ready
to true
, and calls notify()
before the new thread locks the mutex and calls wait()
. If that happens, main
will proceed to its call to wait()
while the new thread is sitting in wait()
, and neither one will notify the other one; they're both waiting for the other one to do something.
If you're unlucky, you won't see this when you're testing the code; it might happen that the new thread starts to wait()
before the main thread calls notify()
, and then the code will work as expected. That's unlucky because sooner or later it will lock up, most likely when you're demonstrating your code to your most important customer.
Wow, thankyou, you are right, I haven't noticed that. Maybe you should remind cppreference about this example.
– Rick
Nov 12 at 9:19
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
Mutex are meant to get a lock on resource, only 1 thread can get that lock. Locking of mutex is atomic, 2 threads cannot acquire a lock on mutex, if they can, then it defeats the purpose of mutex locks!
Mutexes are built such that locking is an atomic operation: it will only complete on one thread at a time, regardless of how many threads are attempting to lock
add a comment |
up vote
3
down vote
accepted
Mutex are meant to get a lock on resource, only 1 thread can get that lock. Locking of mutex is atomic, 2 threads cannot acquire a lock on mutex, if they can, then it defeats the purpose of mutex locks!
Mutexes are built such that locking is an atomic operation: it will only complete on one thread at a time, regardless of how many threads are attempting to lock
add a comment |
up vote
3
down vote
accepted
up vote
3
down vote
accepted
Mutex are meant to get a lock on resource, only 1 thread can get that lock. Locking of mutex is atomic, 2 threads cannot acquire a lock on mutex, if they can, then it defeats the purpose of mutex locks!
Mutexes are built such that locking is an atomic operation: it will only complete on one thread at a time, regardless of how many threads are attempting to lock
Mutex are meant to get a lock on resource, only 1 thread can get that lock. Locking of mutex is atomic, 2 threads cannot acquire a lock on mutex, if they can, then it defeats the purpose of mutex locks!
Mutexes are built such that locking is an atomic operation: it will only complete on one thread at a time, regardless of how many threads are attempting to lock
edited Nov 11 at 7:21
user4581301
19.1k51830
19.1k51830
answered Nov 11 at 7:06
Abhijith Shivaswamy
3115
3115
add a comment |
add a comment |
up vote
1
down vote
"Mutex" is a contraction of "mutual exclusion"; it's purpose is to allow only one thread to lock the mutex at any time.
That said, there's a serious problem in that example. It has a potential deadlock, because it tries too hard to sequence inherently non-sequential operations.
The problem occurs if main
goes through its locking code, sets ready
to true
, and calls notify()
before the new thread locks the mutex and calls wait()
. If that happens, main
will proceed to its call to wait()
while the new thread is sitting in wait()
, and neither one will notify the other one; they're both waiting for the other one to do something.
If you're unlucky, you won't see this when you're testing the code; it might happen that the new thread starts to wait()
before the main thread calls notify()
, and then the code will work as expected. That's unlucky because sooner or later it will lock up, most likely when you're demonstrating your code to your most important customer.
Wow, thankyou, you are right, I haven't noticed that. Maybe you should remind cppreference about this example.
– Rick
Nov 12 at 9:19
add a comment |
up vote
1
down vote
"Mutex" is a contraction of "mutual exclusion"; it's purpose is to allow only one thread to lock the mutex at any time.
That said, there's a serious problem in that example. It has a potential deadlock, because it tries too hard to sequence inherently non-sequential operations.
The problem occurs if main
goes through its locking code, sets ready
to true
, and calls notify()
before the new thread locks the mutex and calls wait()
. If that happens, main
will proceed to its call to wait()
while the new thread is sitting in wait()
, and neither one will notify the other one; they're both waiting for the other one to do something.
If you're unlucky, you won't see this when you're testing the code; it might happen that the new thread starts to wait()
before the main thread calls notify()
, and then the code will work as expected. That's unlucky because sooner or later it will lock up, most likely when you're demonstrating your code to your most important customer.
Wow, thankyou, you are right, I haven't noticed that. Maybe you should remind cppreference about this example.
– Rick
Nov 12 at 9:19
add a comment |
up vote
1
down vote
up vote
1
down vote
"Mutex" is a contraction of "mutual exclusion"; it's purpose is to allow only one thread to lock the mutex at any time.
That said, there's a serious problem in that example. It has a potential deadlock, because it tries too hard to sequence inherently non-sequential operations.
The problem occurs if main
goes through its locking code, sets ready
to true
, and calls notify()
before the new thread locks the mutex and calls wait()
. If that happens, main
will proceed to its call to wait()
while the new thread is sitting in wait()
, and neither one will notify the other one; they're both waiting for the other one to do something.
If you're unlucky, you won't see this when you're testing the code; it might happen that the new thread starts to wait()
before the main thread calls notify()
, and then the code will work as expected. That's unlucky because sooner or later it will lock up, most likely when you're demonstrating your code to your most important customer.
"Mutex" is a contraction of "mutual exclusion"; it's purpose is to allow only one thread to lock the mutex at any time.
That said, there's a serious problem in that example. It has a potential deadlock, because it tries too hard to sequence inherently non-sequential operations.
The problem occurs if main
goes through its locking code, sets ready
to true
, and calls notify()
before the new thread locks the mutex and calls wait()
. If that happens, main
will proceed to its call to wait()
while the new thread is sitting in wait()
, and neither one will notify the other one; they're both waiting for the other one to do something.
If you're unlucky, you won't see this when you're testing the code; it might happen that the new thread starts to wait()
before the main thread calls notify()
, and then the code will work as expected. That's unlucky because sooner or later it will lock up, most likely when you're demonstrating your code to your most important customer.
answered Nov 11 at 17:05
Pete Becker
56.3k439115
56.3k439115
Wow, thankyou, you are right, I haven't noticed that. Maybe you should remind cppreference about this example.
– Rick
Nov 12 at 9:19
add a comment |
Wow, thankyou, you are right, I haven't noticed that. Maybe you should remind cppreference about this example.
– Rick
Nov 12 at 9:19
Wow, thankyou, you are right, I haven't noticed that. Maybe you should remind cppreference about this example.
– Rick
Nov 12 at 9:19
Wow, thankyou, you are right, I haven't noticed that. Maybe you should remind cppreference about this example.
– Rick
Nov 12 at 9:19
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53246550%2fis-it-possible-for-2-threads-lock-a-mutex-at-the-same-time-use-mutex-wrapper%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
std::condition_variable::wait 1) __Atomically releases lock__, blocks the current executing thread, and adds it to the list of threads waiting on *this. The thread will be unblocked when notify_all() or notify_one() is executed. It may also be unblocked spuriously. When unblocked, regardless of the reason, lock is reacquired and wait exits. If this function exits via exception, lock is also reacquired.
– tkausl
Nov 11 at 7:04