I'm trying to understand how multi-threading works.
I have this code:
#include <iostream>
#include <thread>
#include <chrono>
void function1() {
std::cout << "Hi I'm the function 1" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Hi I'm the function 1 after sleeping" << std::endl;
}
void function2() {
std::cout << "Hi I'm the function 2" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "Hi I'm the function 2 after sleeping" << std::endl;
}
int main()
{
while(true) {
std::thread t1(function1);
std::thread t2(function2);
t1.join();
t2.join();
}
system("pause");
return 0;
}
And the problem is when I run it, it stops waiting for std::this_thread::sleep_for(std::chrono::seconds(5)); and doesn't show the next Hi I'm the function 1 from std::thread t1(function1); in the next loop, until the sleep thread ends.
1) Do you know why?
2) I want that the main continues the loop and don't wait to the t2 to finish (sleep_for() from function2 is set to 5 seconds)
This is what your code does:
Start thread 1
Outputs a message
Waits 1 second
Outputs another message
Start thread 2
Outputs a message
Waits 5 seconds
Outputs another message
Waits for both threads to finish
(this will take roughly 5 seconds)
Repeats indefinitely
You have stated that this isn't what you meant to do.
I think, instead, you intended to have the "repeat" inside of each thread, so that they continue ticking independently and indefinitely, like this:
#include <iostream>
#include <thread>
#include <chrono>
void function1() {
while (true) {
std::cout << "Hi I'm the function 1" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Hi I'm the function 1 after sleeping" << std::endl;
}
}
void function2() {
while (true) {
std::cout << "Hi I'm the function 2" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "Hi I'm the function 2 after sleeping" << std::endl;
}
}
int main()
{
std::thread t1(function1);
std::thread t2(function2);
t1.join();
t2.join();
}
Now your code does this:
Start thread 1
Outputs a message
Waits 1 second
Outputs another message
Repeats indefinitely
Start thread 2
Outputs a message
Waits 5 seconds
Outputs another message
Repeats indefinitely
Waits for both threads to finish
(although neither ever will!)
With each thread now spinning independently, neither will ever "block" the other.
1) This is my output and seems what I expect:
Hi I'm the function 1
Hi I'm the function 2
Hi I'm the function 1 after sleeping
Hi I'm the function 2 after sleeping
Hi I'm the function 1
Hi I'm the function 2
Hi I'm the function 1 after sleeping
Hi I'm the function 2 after sleeping
Hi I'm the function 2
Hi I'm the function 1
Hi I'm the function 1 after sleeping
Hi I'm the function 2 after sleeping
Hi I'm the function 2
Hi I'm the function 1
Hi I'm the function 1 after sleeping
Hi I'm the function 2 after sleeping
Hi I'm the function 2
Hi I'm the function 1
2) What you means for best performace???? sleep_for() works everywhere while Sleep is windows specific....
I suggest to use std library where you can, where put sleeps depends on your context...
When you join a thread it will complete its execution and exit. Hence when you joins your thread t1.join(); and t2.join();, the second statement will execute only when first join statement completed. So in your case to crease thread continuously and execute parallel you have to detach the threads like below:-
int i = 0;
while(true) {
std::thread t1(function1);
std::thread t2(function2);
t1.detach();
t2.detach();
//also break your infinite loop here
if( ++i < 4)
break;
}
Related
I have a sample code:
#include <iostream> // std::cout
#include <thread> // std::thread
void pause_thread(int n)
{
if(n != 4)
{
std::this_thread::sleep_for(std::chrono::seconds(100));
std::cout << "pause of " << 100 << " seconds ended\n";
}
std::cout << "Thread number " << n << " ended\n";
}
int main()
{
std::thread threads[6]; // default-constructed threads
std::setvbuf(stdout, NULL, _IONBF, 0);
std::cout << "Spawning 5 threads...\n";
for(int i = 0; i < 5; ++i)
{
//If the object is currently not joinable, it acquires the thread of execution represented by rhs (if any).
//If it is joinable, terminate() is called. If it is joinable, terminate() is called.
//rhs no longer represents any thread of execution
threads[i] = std::move(std::thread(pause_thread, i)); // move-assign threads
}
std::thread& i = threads[4];
threads[5] = std::move(threads[4]);
std::cout << "Done spawning threads. Now waiting for them to join:\n";
for(int i = 0; i < 6; ++i)
{
if(threads[i].joinable())
{
std::cout << "Thread " << i << " " << threads[i].get_id() << " ID joinable" << std::endl << std::flush;
threads[i].join();
}
else
{
std::cout << "Thread " << i << " not joinable" << std::endl << std::flush;
}
}
std::cout << "All threads joined!\n";
return 0;
}
Below is the output I received:
Spawning 5 threads...
Done spawning threads. Now waiting for them to join:
Thread 0 22476 ID joinable
Thread number 4 ended
.... no output for 100 seconds ..
pause of 100 seconds ended
Thread number 0 ended
pause of 100 seconds ended
Thread 1 28676 ID joinable
pause of 100 seconds ended
Thread number 2 ended
Thread number 3 ended
pause of 100 seconds ended
Thread number 1 ended
Thread 2 2336 ID joinable
Thread 3 42236 ID joinable
Thread 4 not joinable
Thread 5 35940 ID joinable
All threads joined!
How the "Thread n xxxx ID joinable" statements are getting printed after "Thread number n ended"? I have even tried using set std::output as non buffered but the output was same?
"Joinable" does not imply that the thread is still executing.
You first join thread #0. This will take ~100 seconds.
During that time, thread #4 finishes since it doesn't sleep, and the other threads are sleeping.
If the threads happen to be scheduled differently, any of the "sleep threads" could be printing that they've ended here.
Once the wait for thread #0 is over, you start joining the other threads.
Some of these have finished executing before you join them and some haven't.
In this particular instance, none of them finished before the wait for thread #0 was over, but there is no guarantee of that happening.
And note that a line like
std::cout << "Thread number " << n << " ended\n";
is not atomic and characters from different threads can be interleaved.
Because joinable does not mean what you think : https://en.cppreference.com/w/cpp/thread/thread/joinable
So any thread that is started is "joinable" it does not need to have finished running.
I am trying to run run() function every 5 seconds without stopping while() loop (parallelly). How can I do that ? Thanks in advance
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
void run()
{
this_thread::sleep_for(chrono::milliseconds(5000));
cout << "good morning" << endl;
}
int main()
{
thread t1(run);
t1.detach();
while(1)
{
cout << "hello" << endl;
this_thread::sleep_for(chrono::milliseconds(500));
}
return 0;
}
In your main function, it is important to understand what each thread is doing.
The main thread creates a std::thread called t1
The main thread continues and detaches the thread
The main thread executes your while loop in which it:
prints hello
sleeps for 0.5 seconds
The main thread returns 0, your program is finished.
Any time from point 1, thread t1 sleeps for 5 seconds and then prints good morning. This happens only once! Also, as pointed out by #Fareanor, std::cout is not thread-safe, so accessing it with the main thread and thread t1 may result in a data race.
When the main thread reaches point 4 (it actually never does because your while loop is infinite), your thread t1 might have finished it's task or not. Imagine the potential problems that could occur. In most of the cases, you'll want to use std::thread::join().
To solve your problem, there are several alternatives. In the following, we will assume that the execution of the function run without the std::this_thread::sleep_for is insignificant compared to 5 seconds, as per the comment of #Landstalker. The execution time of run will then be 5 seconds plus some insignificant time.
As suggested in the comments, instead of executing the function run every 5 seconds, you could simply execute the body of run every 5 seconds by placing a while loop inside of that function:
void run()
{
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
std::cout << "good morning" << std::endl;
}
}
int main()
{
std::thread t(run);
t.join();
return 0;
}
If, for some reason, you really need to execute the run function every 5 seconds as stated in your question, you could launch a wrapper function or lambda which contains the while loop:
void run()
{
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
std::cout << "good morning" << std::endl;
}
int main()
{
auto exec_run = [](){ while (true) run(); };
std::thread t(exec_run);
t.join();
return 0;
}
As a side note, it's better to avoid using namespace std.
Just call your run function in seperate thread function like below. Is this ok for you?
void ThreadFunction()
{
while(true) {
run();
this_thread::sleep_for(chrono::milliseconds(5000));
}
}
void run()
{
cout << "good morning" << endl;
}
int main()
{
thread t1(ThreadFunction);
t1.detach();
while(1)
{
cout << "hello" << endl;
this_thread::sleep_for(chrono::milliseconds(500));
}
return 0;
}
Currently I'm working on server development for an online game and decided to implement it as multithreaded application.
I have a main thread which implements while loop which abstractly gets data from the socket.
std::vector<std::thread> games_threads;
int start(int game_id) {
std::this_thread::sleep_for(std::chrono::seconds(10));
return end(game_id);
}
int end(int game_id) {
// some other conditions for turn end
return start(game_id);
}
int main() {
// socket implmementation
while(1) {
Message msg = socket.get_data();
switch(msg->action) {
case GAME_START:
std::thread game_thread(start, create_game());
game_thread.detach();
games_threads.push_back(game_thread);
break;
case TURN_END:
std::thread game_thread(end, msg->get_game());
game_thread.detach();
games_threads.push_back(game_thread);
break;
}
}
}
Game creates with turn start() method. And then after waiting 10 secs in call end() method which implements turn end.
After than turn end() method calls start().
But I need also implement force turn end method so I have race condition with 2 cases:
Start -> End normal workflow with 10s timeout (which makes game
thread unavailable for 10 secs)
Forced turn end command (TURN_END).
So I need somehow end the current game thread and replace with one user thread. Or just catch signals somehow with conditional variable but I have already freeze for 10sec and as far as I know I can't wait both things at the same time (conditional variable and sleep ending).
Maybe multithreading is not a good solution at all. Please share your approach in this case.
Thanks
Its not so much that multi-threading is a bad approach as your specific implementation is not right.
A call to the start() function or end() function will never return because they each call each other in a never ending recursion. This is already bad since your stack will be filling up as you enter deeper into function calls.
But that aside, your main loop starts a new thread when you call GAME_START and this new thread goes into its "forever" start()<-->end() loop. "OK" so far, but then when the TURN_END is called your main loop calls end() directly and therefore your main loop also now enters a forever start()<-->end() loop. This now means both your main and your "worker" thread are locked up in these loops that don't return - so no more messages can be processed from your socket.
I would suggest that your main loop uses a condition variable to signal your worker loop to force a new turn.
I am not quite sure what to suggest to replace your start()<-->end() recursion loop because its not clear to me what this is trying to achieve. But possibly a timer class might work here (the example is the first one I found in google)
Complete Example Using Stdin
Here the start function implements a thread loop instead of calling end/start repeatedly... Also the game ID 1 gets ended when you enter end the other games continue as normal. All games exit when you enter exit
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <algorithm>
#include <atomic>
#include <chrono>
#include <condition_variable>
std::vector<std::thread> games_threads;
std::condition_variable cv;
std::mutex cv_m;
int the_game_id = 0;
int start(int id) {
int game_id = id;
bool running = true;
while (running)
{
std::unique_lock<std::mutex> lk(cv_m);
auto now = std::chrono::system_clock::now();
std::cout << "THREAD " << game_id << ": Waiting for turn..." << std::endl;
// Wait for the signal to end turn only if the game ID is for us.
if(cv.wait_until(lk, now + std::chrono::seconds(10), [&game_id](){return (the_game_id == game_id || the_game_id == -1);}))
{
// Condition var signalled
if (the_game_id == -1)
{
std::cout << "THREAD" << game_id << ": end game - exit" << std::endl;
running = false;
}
else
{
std::cout << "THREAD" << game_id << ": turn end forced" << std::endl;
// Reset the game ID so we don't keep triggering
the_game_id = 0;
}
}
else
{
// 10 second timeout occured
std::cout << "THREAD" << game_id << ": 10 seconds is up, end turn" << std::endl;
}
}
std::cout << "THREAD" << game_id << ": ended" << std::endl;
return 1;
}
int main() {
// pretend socket implmementation - using stdin
int id = 1;
bool done = false;
while(!done) {
std::string cmd;
std::getline(std::cin, cmd);
if (cmd == "start")
{
std::cout << "starting..." << std::endl;
games_threads.push_back({ std::thread( [&id](){ return start(id++); } ) });
}
else if (cmd == "end")
{
std::cout << "ending..." << std::endl;
// Notify game ID 1 to end turn - (but in reality get the ID from the message)
the_game_id = 1;
cv.notify_all();
}
else if (cmd == "exit")
{
std::cout << "exiting all threads..." << std::endl;
// Notify game ID 1 to end turn
the_game_id = -1;
cv.notify_all();
done = true;
}
}
// Tidyup threads
for (auto &th : games_threads)
{
if (th.joinable())
{
th.join();
}
}
}
Output:
> start
starting...
THREAD 1: Waiting for turn...
> start
starting...
THREAD 2: Waiting for turn...
> start
starting...
THREAD 3: Waiting for turn...
> end
ending...
THREAD1: turn end forced
THREAD 1: Waiting for turn...
THREAD2: 10 seconds is up, end turn
THREAD 2: Waiting for turn...
THREAD3: 10 seconds is up, end turn
THREAD 3: Waiting for turn...
THREAD1: 10 seconds is up, end turn
THREAD 1: Waiting for turn...
> exit
exiting all threads...
THREAD1: end game - exit
THREAD1: ended
THREAD2: end game - exit
THREAD2: ended
THREAD3: end game - exit
THREAD3: ended
I have written a small test program to understand the signal and slot mechanism provided by boost and their behavior when posted in different thread. I want to have slot's being called in different threads but the output of my program shows slots are not being called in different thread from which signal was emitted.
#include <iostream>
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <boost/random.hpp>
#include <boost/signals2.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/signals2/signal.hpp>
boost::signals2::signal<void (int)> randomNumberSig;
// ---------------- Thread 1 ----------------
boost::asio::io_service thread1_serv;
void handle_rnd_1(int number)
{
std::cout << "Thread1: " << boost::this_thread::get_id() << " & Number is " << number << std::endl;
}
void thread1_init(void)
{
std::cout << "Thread 1 Init" << std::endl;
boost::asio::io_service::work work (thread1_serv);
randomNumberSig.connect([] (int num) -> void {
std::cout << "Slot called from main thread" << std::endl;
thread1_serv.post(boost::bind(handle_rnd_1, num));
});
}
void thread1_loop(void)
{
}
void thread1(void)
{
thread1_init();
while (true) {
thread1_serv.run();
thread1_loop();
}
}
int main(int argc, char *argv[])
{
std::cout << "Starting the Program" << std::endl;
boost::thread t1(&thread1);
while (1) {
int num = 2;
std::cout << "Thread " << boost::this_thread::get_id() << " & Number: " << num << std::endl;
randomNumberSig(num);
boost::this_thread::sleep_for(boost::chrono::seconds(num));
}
return 0;
}
The output of the program is:
Starting the Program
Thread 7fae3a2ba3c0 & Number: 2
Thread 1 Init
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
I suspect post() method of the io_service is not working properly or I have missed something in initializing the io_service.
You don't handle invocation of run function properly.
You used work to prevent run from ending when there is no work to do.
But your work is local inside thread1_init so when this function ends, work
is destroyed and io_service::run exits when there are no handlers to be called.
After run finished, io_service is marked as stopped, and you need to call restart before
calling run (as subsequent invocation).
If you don't call restart, run returns immediately without processing any handlers - that is why you don't see them.
So first solution is to create work whose lifetime is the same as io_service (just use global variable - ugly):
boost::asio::io_service thread1_serv;
boost::asio::io_service::work work(thread1_serv);
Another solution, don't use work, just call restart before run:
thread1_init();
while (true) {
thread1_serv.restart();
thread1_serv.run();
thread1_loop();
}
Wandbox test
I have a code, and i'm testing how much time will take an executing of 10 threads.
#include <iostream>
#include <thread>
#include <chrono>
#include <time.h>
using namespace std;
void pause_thread(int n){
this_thread::sleep_for(chrono::seconds(n));
cout << "pause of " << n << " seconds ended\n";
}
int main(){
clock_t EndTime = clock();
thread threads[10];
cout << "Spawning 10 threads...\n";
for (int i = 0; i<10; ++i)
threads[i] = thread(pause_thread, i + 1);
cout << "Done spawning threads. Now waiting for them to join:\n";
for (int i = 0; i<10; ++i)
threads[i].join();
cout << "All threads joined!\n";
cout << "==================================================\n";
cout << "Time of executing threads: " << (double)(clock() - EndTime) / CLOCKS_PER_SEC << endl;
system("pause");
return 0;
}
The output is this:
Spawning 10 threads...
Done spawning threads. Now waiting for them to join:
pause of 1 seconds ended
pause of 2 seconds ended
pause of 3 seconds ended
pause of 4 seconds ended
pause of 5 seconds ended
pause of 6 seconds ended
pause of 7 seconds ended
pause of 8 seconds ended
pause of 9 seconds ended
pause of 10 seconds ended
All threads joined!
==================================================
Time of executing threads: 10.041
First question is: Why execution of the program takes 10,041 seconds if the pause between each thread is 1 second? What happened with the program and it took additional 0.041s on executing?
Second question is: Is this right way to execute thread in another thread?
threads[i] = thread(...);
Is this mean that thread is in the thread?
If not, how can it be done (to execute thread in another thread)?
First question is well answered by Brandon Haston's comment.
Answer to second question doesn't fit in a comment.
threads[i] = thread(...);
means that a std::thread has been created and its representative std::thread object has been assigned to a slot in your std::thread array. This raises a question I'm going to have to look into on my own later when I have a compiler to play with: What happened to the thread that was just overwritten?
Anyway, that new thread isn't inside another thread. Threads don't have any concept of ownership mutual. A process owns threads, but threads don't. A thread can start another thread. For example,
void pause_thread(int n){
this_thread::sleep_for(chrono::seconds(n));
cout << "pause of " << n << " seconds ended\n";
if (! cows_are_home)
{
thread newthread(pause_thread, 1);
newthread.detach();
}
}
Each new thread will wait about 1 second, then create a thread which will wait a second and create another thread, and this will go on until the cows come home.