List share between two threads - c++

I would like in c++ to share a list between two threads. I would like very simple not by taking FIFO or Shared memory so i just use mutex and locks.
I tried this way and its working :
#include <string.h>
#include <mutex>
#include <iostream>
#include <thread>
#include <list>
std::list<int> myList;
std::mutex list_mutex;
void client(){
std::lock_guard<std::mutex> guard(list_mutex);
myList.push_back(4);
};
void server(){
std::lock_guard<std::mutex> guard(list_mutex);
myList.push_back(2);
};
void print(std::list<int> const &list)
{
for (auto const& i: list) {
std::cout << i << "\n";
}
};
int main(int ac, char** av)
{
std::mutex list_mutex;
std::thread t1(client);
std::thread t2(server);
t1.join();
t2.join();
print(myList);
std::cout<<"test";
return 0;
}
And it print me this
24test
This is fine it work HOWEVER i'm not sure i'm using the same lock ? My supervisor wants me to have explicit Lock/Unlock in the code. At least if i can use the same mutex?
Thank you very much to help me

Ted's comment is important, what you are working with are threads, not processes. Processes don't share memory (besides using Shared Memory, but you wanted to avoid that). Threads share their entire memory space with each other.
You also mentioned that your supervisor wants you to use unlock/lock sections. You could do this by calling:
list_mutex.lock()
... critical section ...
list_mutx.unlock()
But you already do this implicitly by constructing a lock_guard. The lock_guard locks when you create it and unlocks at the end of the current scope.
As noted by Ted, you need to remove the second declaration of list_mutex (inside main).

Related

What is the scope of std::mutex object?

Here is the sample code:
#include <iostream>
#include <thread>
#include <mutex>
int value = 0;
void criticalSection(int changeValue)
{
std::mutex mtx;
std::unique_lock<std::mutex> uniqueLock(mtx);
value = changeValue;
std::cout << value << std::endl;
uniqueLock.unlock();
uniqueLock.lock();
++value;
std::cout << value << std::endl;
}
int main(int argc, char **argv)
{
std::thread t1(criticalSection, 1), t2(criticalSection, 2);
t1.join();
t2.join();
return 0;
}
My question is: what is the scope of mtx in the above code? Will each thread create a mtx within that thread? Is there any difference if I specify mtx as a global variable instead of a local variable?
I just started to learn multithread in C++. Thank you very much for your help.
There are no special scoping rules for mutexes. Their scope ends on the next }. In your code every call to criticalSection creates a new mutex instance. Hence, the mutex cannot possibly be used to synchronize the two threads. To do so, both threads would need to use the same mutex.
You can pass a reference to a mutex to the function:
#include <iostream>
#include <thread>
#include <mutex>
int value = 0;
void criticalSection(int changeValue,std::mutex& mtx)
{
std::unique_lock<std::mutex> uniqueLock(mtx);
//...
}
int main(int argc, char **argv)
{
std::mutex mtx;
std::thread t1(criticalSection, 1,std::ref(mtx)), t2(criticalSection, 2,std::ref(mtx));
t1.join();
t2.join();
return 0;
}
Alternatively you could use a std::atomic<int> value; and drop the mutex when value is the only shared state.
The mutex type doesn't change C++ rules on how variables and objects work.
If you declare a non-static variable on the stack, each call to that function will create its own version of that variable. Regardless of which thread it is. These are all separate and distinct objects.
When you lock a mutex, you are locking that object. Other objects of the same type are unrelated to that lock.
To make a mutex useful, both of the pieces of code trying to lock it must be locking the same object. How you accomplish this is ultimately up to your needs.

how to initialize a unique lock that has already been declared in c++?

I created a class and I declared an array of unique locks and an array of mutexes as private variables.
My question is how do I connect the two of them in the constructor of the class?
header file:
#include <iostream>
#include <mutex>
#include <string>
#define PHILO_NUM 5
class philosophers
{
private:
std::mutex _mu[5];
std::unique_lock<std::mutex> _fork[5], _screen;
std::mutex _screenMutex;
public:
philosophers();
};
c++ file:
#include "philosophers .h"
philosophers::philosophers()
{
for (int i = 0; i < PHILO_NUM; i++)
{
// Somehow connect this->_forks[i] and this->_mu[i]
}
// At the end connect this->_screen and this->_screenMutex
}
It is not easy to say what you should be doing since you do not tell what you want to do. I think you mixed locks and mutexes a bit up. There is no reason to share the locks (as you try to do here). You need to share the mutexes, but one mutex can be associated with arbitrary many std::unique_locks (but only one of them can lock the mutex at the same time).
So, I would implement your class as follows:
#include <mutex>
constexpr size_t PHILO_NUM = 5;
class philosophers
{
private:
std::mutex _mu[PHILO_NUM];
std::mutex _screenMutex;
public:
philosophers() = default; // Nothing to do here
std::unique_lock grab_fork(size_t index) {
return std::unique_lock (_mu[index]);
}
};
So, if someone grabs a fork, they can use it as long as they hold a lock to that fork. An example use would look like this:
philosophers p;
void eat() {
auto lock = p.grab_fork(3);
// Now I can eat
lock.unlock(); // Not really necessary, lock will release the mutex, when it is destroyed at the end of the scope
}

what are the use cases for std::unique_lock::release?

In what situations would one use the release method of std::unique_lock ?
I made the mistake of using the release method instead of the unlock method and it took a while to understand why the following code wasn't working.
#include <mutex>
#include <iostream>
#include <vector>
#include <thread>
#include <chrono>
std::mutex mtx;
void foo()
{
std::unique_lock<std::mutex> lock(mtx);
std::cout << "in critical section\n";
std::this_thread::sleep_for(std::chrono::seconds(1));
lock.release();
}
int main()
{
std::vector<std::thread> threads;
for (int i = 0; i < 5; ++i)
threads.push_back(std::thread(foo));
for (std::thread& t : threads)
t.join();
}
There's a good use for it in this answer where ownership of the locked state is explicitly transferred from a function-local unique_lock to an external entity (a by-reference Lockable parameter).
This concrete example is typical of the use: To transfer ownership of the locked state from one object (or even type) to another.
.release() is useful when you want to keep the mutex locked until some other object/code decides to unlock it... for example, if you were calling into a function that needed the mutex locked and would unlock it itself at a certain point in that function's processing, where that function accepts only a std::mutex& rather than a std::unique_lock<std::mutex>&&. (Conceptually similar to the uses for smart pointer release functions.)

Synchronise two threads passing events between each other

I am new to windows c++ programming. Please see the below code where I want to make the two threads synchronized. The first thread should print "Hello" then pass the control/event to the second thread. Not sure how to do it. As of now I am using Sleep(1000). But if I dont use Sleep it result into undefined behavior. Please help...
#include <windows.h>
#include <process.h>
#include <iostream>
void thread1(void*);
void thread2(void*);
int main(int argc, char **argv) {
_beginthread(&thread1,0,(void*)0);
_beginthread(&thread2,0,(void*)0);
Sleep(1000);
}
void thread1(void*)
{
std::cout<<"Hello "<<std::endl;
}
void thread2(void*)
{
std::cout<<"World"<<std::endl;
}
The problem is the question you are asking really doesn't make sense. Multiple threads are designed to run at the same time and you're trying to play a game of pass the buck from one thread to another to get sequential serialised behavoir. Its like taking a really complicated tool and ask how it solves what is normally a really easy question.
However, multithreading is a really important topic to learn so I'll try to answer what you need to the best of my ability.
Firstly, I'd recommend using the new, standard C++11 functions and libraries. For windows, you can download Visual Studio 2012 Express Edition to play about with.
With this you can use std::thread, std::mutex and a lot [but not all] of the other C++11 goodies (like std::condition_variable).
To solve your problem you really need a condition variable. This lets you signal to another thread that something is ready for them:
#include <iostream>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <thread>
static std::atomic<bool> ready;
static std::mutex lock;
static std::condition_variable cv;
// ThreadOne immediately prints Hello then 'notifies' the condition variable
void ThreadOne()
{
std::cout << "Hello ";
ready = true;
cv.notify_one();
}
// ThreadTwo waits for someone to 'notify' the condition variable then prints 'World'
// Note: The 'cv.wait' must be in a loop as spurious wake-ups for condition_variables are allowed
void ThreadTwo()
{
while(true)
{
std::unique_lock<std::mutex> stackLock(lock);
cv.wait(stackLock);
if(ready) break;
}
std::cout << "World!" << std::endl;
}
// Main just kicks off two 'std::thread's. We must wait for both those threads
// to finish before we can return from main. 'join' does this - its the std
// equivalent of calling 'WaitForSingleObject' on the thread handle. its necessary
// to call join as the standard says so - but the underlying reason is that
// when main returns global destructors will start running. If your thread is also
// running at this critical time then it will possibly access global objects which
// are destructing or have destructed which is *bad*
int main(int argc, char **argv)
{
std::thread t1([](){ThreadOne();});
std::thread t2([](){ThreadTwo();});
t1.join();
t2.join();
}
Here is the simplified version to handle your situation.
You are creating 2 threads to call 2 different function.
Ideally thread synchronization is used to serialize same code between threads but in your case it is not the need. You are trying to serialize 2 threads which are no way related to one another.
Any how you can wait for each thread to finish by not making async call.
#include <windows.h>
#include <process.h>
#include <iostream>
#include<mutex>
using namespace std;
void thread1(void*);
void thread2(void*);
int main(int argc, char **argv) {
HANDLE h1 = (HANDLE)_beginthread(&thread1,0,(void*)0);
WaitForSingleObject(h1,INFINITE);
HANDLE h2 = (HANDLE)_beginthread(&thread2,0,(void*)0);
WaitForSingleObject(h2,INFINITE);
}
void thread1(void*)
{
std::cout<<"Hello "<<std::endl;
}
void thread2(void*)
{
std::cout<<"World"<<std::endl;
}
You can group both beginthread in single function and call that function in while loop if you want to print multiple times.
void fun()
{
HANDLE h1 = (HANDLE)_beginthread(&thread1,0,(void*)0);
WaitForSingleObject(h1,INFINITE);
HANDLE h2 = (HANDLE)_beginthread(&thread2,0,(void*)0);
WaitForSingleObject(h2,INFINITE);
}

Creating a lock that preserves the order of locking attempts in C++11

Is there a way to ensure that blocked threads get woken up in the same order as they got blocked? I read somewhere that this would be called a "strong lock" but I found no resources on that.
On Mac OS X one can design a FIFO queue that stores all the thread ids of the blocked threads and then use the nifty function pthread_cond_signal_thread_np() to wake up one specific thread - which is obviously non-standard and non-portable.
One way I can think of is to use a similar queue and at the unlock() point send a broadcast() to all threads and have them check which one is the next in line.
But this would induce lots of overhead.
A way around the problem would be to issue packaged_task's to the queue and have it process them in order. But that seems more like a workaround to me than a solution.
Edit:
As pointed out by the comments, this question may sound irrelevant, since there is in principle no guaranteed ordering of locking attempts.
As a clarification:
I have something I call a ConditionLockQueue which is very similar to the NSConditionLock class in the Cocoa library, but it maintains a FIFO queue of blocked threads instead of a more-or-less random pool.
Essentially any thread can "line up" (with or without the requirement of a specific 'condition' - a simple integer value - to be met). The thread is then placed on the queue and blocks until it is the frontmost element in the queue whose condition is met.
This provides a very flexible way of synchronization and I have found it very helpful in my program.
Now what I really would need is a way to wake up a specific thread with a specific id.
But these problems are almost alike.
Its pretty easy to build a lock object that uses numbered tickets to insure that its completely fair (lock is granted in the order threads first tried to acquire it):
#include <mutex>
#include <condition_variable>
class ordered_lock {
std::condition_variable cvar;
std::mutex cvar_lock;
unsigned int next_ticket, counter;
public:
ordered_lock() : next_ticket(0), counter(0) {}
void lock() {
std::unique_lock<std::mutex> acquire(cvar_lock);
unsigned int ticket = next_ticket++;
while (ticket != counter)
cvar.wait(acquire);
}
void unlock() {
std::unique_lock<std::mutex> acquire(cvar_lock);
counter++;
cvar.notify_all();
}
};
edit
To fix Olaf's suggestion:
#include <mutex>
#include <condition_variable>
#include <queue>
class ordered_lock {
std::queue<std::condition_variable *> cvar;
std::mutex cvar_lock;
bool locked;
public:
ordered_lock() : locked(false) {};
void lock() {
std::unique_lock<std::mutex> acquire(cvar_lock);
if (locked) {
std::condition_variable signal;
cvar.emplace(&signal);
signal.wait(acquire);
} else {
locked = true;
}
}
void unlock() {
std::unique_lock<std::mutex> acquire(cvar_lock);
if (cvar.empty()) {
locked = false;
} else {
cvar.front()->notify_one();
cvar.pop();
}
}
};
I tried Chris Dodd solution
https://stackoverflow.com/a/14792685/4834897
but the compiler returned errors because queues allows only standard containers that are capable.
while references (&) are not copyable as you can see in the following answer by Akira Takahashi :
https://stackoverflow.com/a/10475855/4834897
so I corrected the solution using reference_wrapper which allows copyable references.
EDIT: #Parvez Shaikh suggested small alteration to make the code more readable by moving cvar.pop() after signal.wait() in lock() function
#include <mutex>
#include <condition_variable>
#include <queue>
#include <atomic>
#include <vector>
#include <functional> // std::reference_wrapper, std::ref
using namespace std;
class ordered_lock {
queue<reference_wrapper<condition_variable>> cvar;
mutex cvar_lock;
bool locked;
public:
ordered_lock() : locked(false) {}
void lock() {
unique_lock<mutex> acquire(cvar_lock);
if (locked) {
condition_variable signal;
cvar.emplace(std::ref(signal));
signal.wait(acquire);
cvar.pop();
} else {
locked = true;
}
}
void unlock() {
unique_lock<mutex> acquire(cvar_lock);
if (cvar.empty()) {
locked = false;
} else {
cvar.front().get().notify_one();
}
}
};
Another option is to use pointers instead of references, but it seems less safe.
Are we asking the right questions on this thread??? And if so: are they answered correctly???
Or put another way:
Have I completely misunderstood stuff here??
Edit Paragraph: It seems StatementOnOrder (see below) is false. See link1 (C++ threads etc. under Linux are ofen based on pthreads), and link2 (mentions current scheduling policy as the determining factor) -- Thanks to Cubbi from cppreference (ref). See also link, link, link, link. If the statement is false, then the method of pulling an atomic (!) ticket, as shown in the code below, is probably to be preferred!!
Here goes...
StatementOnOrder: "Multiple threads that run into a locked mutex and thus "go to sleep" in a particular order, will afterwards aquire ownership of the mutex and continue on in the same order."
Question: Is StatementOnOrder true or false ???
void myfunction() {
std::lock_guard<std::mutex> lock(mut);
// do something
// ...
// mutex automatically unlocked when leaving funtion.
}
I'm asking this because all code examples on this page to date, seem to be either:
a) a waste (if StatementOnOrder is true)
or
b) seriously wrong (if StatementOnOrder is false).
So why do a say that they might be "seriously wrong", if StatementOnOrder is false?
The reason is that all code examples think they're being super-smart by utilizing std::condition_variable, but are actually using locks before that, which will (if StatementOnOrder is false) mess up the order!!!
Just search this page for std::unique_lock<std::mutex>, to see the irony.
So if StatementOnOrder is really false, you cannot run into a lock, and then handle tickets and condition_variables stuff after that. Instead, you'll have to do something like this: pull an atomic ticket before running into any lock!!!
Why pull a ticket, before running into a lock? Because here we're assuming StatementOnOrder to be false, so any ordering has to be done before the "evil" lock.
#include <mutex>
#include <thread>
#include <limits>
#include <atomic>
#include <cassert>
#include <condition_variable>
#include <map>
std::mutex mut;
std::atomic<unsigned> num_atomic{std::numeric_limits<decltype(num_atomic.load())>::max()};
unsigned num_next{0};
std::map<unsigned, std::condition_variable> mapp;
void function() {
unsigned next = ++num_atomic; // pull an atomic ticket
decltype(mapp)::iterator it;
std::unique_lock<std::mutex> lock(mut);
if (next != num_next) {
auto it = mapp.emplace(std::piecewise_construct,
std::forward_as_tuple(next),
std::forward_as_tuple()).first;
it->second.wait(lock);
mapp.erase(it);
}
// THE FUNCTION'S INTENDED WORK IS NOW DONE
// ...
// ...
// THE FUNCTION'S INDENDED WORK IS NOW FINISHED
++num_next;
it = mapp.find(num_next); // this is not necessarily mapp.begin(), since wrap_around occurs on the unsigned
if (it != mapp.end()) {
lock.unlock();
it->second.notify_one();
}
}
The above function guarantees that the order is executed according to the atomic ticket that is pulled. (Edit: using boost's intrusive map, an keeping condition_variable on the stack (as a local variable), would be a nice optimization, which can be used here, to reduce free-store usage!)
But the main question is:
Is StatementOnOrder true or false???
(If it is true, then my code example above is a also waste, and we can just use a mutex and be done with it.)
I wish somebody like Anthony Williams would check out this page... ;)