Threat
In C++ you can provide concurrency by using threat.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <iostream> #include <thread> #include <chrono> void myThread(){ std::cout << "thread runs : " <<std::this_thread::get_id() << std::endl; std::this_thread::sleep_for(std::chrono::seconds(4)); std::cout << "Thread ends" << std::endl; } int main() { std::thread th(myThread); std::cout << "Normal rutine" << std::endl; // join waits main thread until child thread ends. th.join(); } |
join method creates waiting for the main thread. But detach stop connection between the main thread and created child thread.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include <iostream> #include <thread> #include <chrono> void myThread(){ std::cout << "thread runs : " <<std::this_thread::get_id() << std::endl; std::this_thread::sleep_for(std::chrono::seconds(4)); std::cout << "Thread ends" << std::endl; } int main() { std::thread th(myThread); //main thread will not wait th.detach(); std::cout << "Normal rutine" << std::endl; //if the child thread joinable please join it // but it is detached if(th.joinable()) th.join(); //this line won't work. std::this_thread::sleep_for(std::chrono::seconds(10)); } |
Passing argument
You can also pass an argument to the thread. You can simply use the parameter on thread method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#include <iostream> #include <thread> #include <chrono> class SimpleClass{ public: SimpleClass(){ std::cout << "SimpleClass()" << std::endl; } SimpleClass(const SimpleClass &s){ std::cout << "SimpleClass(const SimpleClass &s)" << std::endl; } SimpleClass(SimpleClass && s){ std::cout << "SimpleClass(SimpleClass && s)" << std::endl; } ~SimpleClass(){ std::cout << "~SimpleClass()" << std::endl; } }; void myThread(SimpleClass s){ std::cout << "thread runs : " <<std::this_thread::get_id() << std::endl; } int main() { SimpleClass s{}; std::thread th(myThread, s); th.join(); std::cout << "Program ends" << std::endl; } |
But it creates several copies of the object. The best way is using pointer but you can’t pass pointer directly. There is a helper std:ref
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#include <iostream> #include <thread> #include <chrono> class SimpleClass{ public: SimpleClass(){ std::cout << "SimpleClass()" << std::endl; } SimpleClass(const SimpleClass &s){ std::cout << "SimpleClass(const SimpleClass &s)" << std::endl; } SimpleClass(SimpleClass && s){ std::cout << "SimpleClass(SimpleClass && s)" << std::endl; } ~SimpleClass(){ std::cout << "~SimpleClass()" << std::endl; } }; void myThread(SimpleClass &s){ std::cout << "thread runs : " <<std::this_thread::get_id() << std::endl; } int main() { SimpleClass s{}; std::thread th(myThread, std::ref(s)); th.join(); std::cout << "Program ends" << std::endl; } |
on the other hand, you may use std:cref for constant references
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#include <iostream> #include <thread> #include <chrono> class SimpleClass{ public: SimpleClass(){ std::cout << "SimpleClass()" << std::endl; } SimpleClass(const SimpleClass &s){ std::cout << "SimpleClass(const SimpleClass &s)" << std::endl; } SimpleClass(SimpleClass && s){ std::cout << "SimpleClass(SimpleClass && s)" << std::endl; } ~SimpleClass(){ std::cout << "~SimpleClass()" << std::endl; } }; void myThread(const SimpleClass &s){ std::cout << "thread runs : " <<std::this_thread::get_id() << std::endl; } int main() { SimpleClass s{}; std::thread th(myThread, std::cref(s)); th.join(); std::cout << "Program ends" << std::endl; } |
Using the same variables with mutex
If multiple threads use a variable. You have to create a mutex system. A mutex has two important methods: lock and unlock.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include <iostream> #include <thread> #include <chrono> #include <mutex> int main() { // create a mutex std::mutex m_mutex{}; int i{0}; auto fn = [&i, &m_mutex](int x){ for(int j = 0; j < x; j++){ // lock that mutex m_mutex.lock(); i++; std::this_thread::sleep_for(std::chrono::milliseconds(500)); std::cout << std::this_thread::get_id() << " -- " << i << std::endl; m_mutex.unlock(); } }; std::thread th1(fn, 10); std::thread th2(fn, 10); th1.join(); th2.join(); } |