how to generate many threads by std::thread? - c++

As we all known, we can generate one thread by std::thread t1(func); link
But how can we create 20 threads by vector?

An example solution would be:
std::vector<std::thread> my_threads{};
my_threads.reserve(20);
for(int i = 0; i < 20; i++)
my_threads.emplace_back([i]{
std::cout << "[" << i << "] Going to sleep\n";
this_thread::sleep_for(std::chrono::seconds{1});
std::cout << "[" << i << "] Hey I'm back :)\n";
});
for(auto& thread : my_threads)
if(thread.joinable())
thread.join();
Pay attention to the last tree lines.
If you don't join or detach your threads you'll get an abort.
This prevents your application from leaking unmanaged threads.

Related

In the example of std::atomic<T>::exchange, why the count of times is not 25?

The example I talked about is this one on cppreference.com.
The code snippet is pasted below.
int main(){
const std::size_t ThreadNumber = 5;
const int Sum = 5;
std::atomic<int> atom{0};
std::atomic<int> counter{0};
// lambda as thread proc
auto lambda = [&](const int id){
for (int next = 0; next < Sum;){
// each thread is writing a value from its own knowledge
const int current = atom.exchange(next);
counter++;
// sync writing to prevent from interrupting by other threads
std::osyncstream(std::cout)
<< '#' << id << " (" << std::this_thread::get_id()
<< ") wrote " << next << " replacing the old value "
<< current << '\n';
next = std::max(current, next) + 1;
}
};
std::vector<std::thread> v;
for (std::size_t i = 0; i < ThreadNumber; ++i){
v.emplace_back(lambda, i);
}
for (auto& tr : v){
tr.join();
}
std::cout << ThreadNumber << " threads adding 0 to "
<< Sum << " takes total "
<< counter << " times\n";
}
To me, the value of counter is 25 because 5 threads and each thread loops 5 times. However, the shown output is 16. I also ran it myself, the possible value varies, but it never gets to be 25.
Why the printed value of counter is actually smaller?
Consider one of the possible executions:
Lets say one of the threads finishes the loop before other threads start.
This gives you atom == 4. The next thread to enter the loop will get current == 4 and will exit the loop after the first iteration.
This way the second thread increments current once instead of 5 times like you expect it to.
I haven't taken the trouble to analyse the code in detail, but the for loop in the lambda is broken (or, at least, not doing what you are expecting it to do). If you replace it with something more straightforward, namely:
for (int next = 0; next < Sum; ++next){
then 25 is output.

Read and modify a vector by multi-threading

I want to create a vector of threads which will doing same job, in my case I just want to take information from a vector of integers.
For example;
I will have got 4 threads and 10 integers.
My threads will get the integers' values. That's all. So I've coded this part but I couldn't solve how can I manage thread vector. How can I read values from this vector by waiting for each thread for the other thread? I would appreciate it if you explain with a sample code snippet.
std::condition_variable cond;
std::mutex m_mutex;
std::atomic<int> position_holder {0};
void access_fonksiyon(std::vector<int> myvec){
std::unique_lock<std::mutex> locked {m_mutex};
position_holder++;
std::cout << "Locked." << std::endl;
std::cout << "Position holder value : "
<< position_holder
<< "thread ID: "
<< std::this_thread::get_id()
<< std::endl;
}
int main(){
std::vector<int> myvec = {1,2,3,4,5,6,7,8,9};
std::vector<std::thread> thread_vec;
for(int i = 0; i < 2; i++){
thread_vec.push_back(std::thread(access_fonksiyon, std::ref(myvec)));
}
for (std::thread &reader : thread_vec){
reader.join();
}
return 0;
}

Is std::map insert thread safe?

I know that the std::map class is thread unsafe in read and write in two threads. But is it OK to insert in multiple threads?
void writeMap()
{
for (int i = 0; i < 1000; i++)
{
long long random_variable = (std::rand()) % 1000;
std::cout << "Thread ID -> " << std::this_thread::get_id() << " with looping index " << i << std::endl;
k1map.insert(std::make_pair(i, new p(i)));
}
}
int main()
{
std::srand((int)std::time(0));
for (int i = 0; i < 1000; ++i)
{
long long random_variable = (std::rand()) % 1000;
std::thread t(writeMap);
std::cout << "Thread created " << t.get_id() << std::endl;
t.detach();
}
return 0;
}
Like such code is running normal no matter how many times I try.
program is complex,to some extent,like magic(LOL).
The code run results are different on various IDE.
Before, I used VS2013, it's always right.
But on vs19 and linux,the result of the same code is wrong.
Maybe on vs2013,the implement of MAP has special way.
No, std::map::insert is not thread-safe.
Most standard library types are thread safe only if you are using separate object instances in separate threads. Take a look at the thread safety part of container's docs.
As #NutCracker has mentioned, std::map::insert is not thread-safe.
But, if the posted code works fine, I think the reason is that the map fills very fast by one thread and as a result, other threads are not modifying the map anymore.

Do i have to mutex a reading operation while other threads are writing thread safe?

i am confused in a specific multithreading situation and couldn´t find clear explanations to this scenario. In the code below two custom threads are writing+reading thread safe but the main thread is also reading concurrently. So here is my question: Do i have to mutex the read function, too? Or is it absolutly impossible to crash the app maybe cause of previously deleted pointers in the vector for example? I hope you guys can help me, Thanks!
#include <thread>
#include <mutex>
#include <iostream>
#include <vector>
int g_i = 0;
std::vector<int> test;
std::mutex g_i_mutex; // protects g_i
void safe_increment()
{
std::lock_guard<std::mutex> lock(g_i_mutex);
++g_i;
test.resize(test.size() + 1, 2);
std::cout << std::this_thread::get_id() << ": " << g_i << '\n';
for (std::vector<int>::const_iterator i = test.begin(); i != test.end(); ++i)
std::cout << std::this_thread::get_id() << " thread vector: " << *i << '\n';
// g_i_mutex is automatically released when lock
// goes out of scope
}
void request_threadedvar()
{
for (std::vector<int>::const_iterator i = test.begin(); i != test.end(); ++i)
std::cout << std::this_thread::get_id() << " request threaded vector: " << *i << '\n';
}
int main()
{
std::cout << "main: " << g_i << '\n';
test.resize(test.size() + 1, 1);
for (std::vector<int>::const_iterator i = test.begin(); i != test.end(); ++i)
std::cout << "main vector: " << *i << '\n';
std::thread t1(safe_increment);
request_threadedvar();
std::thread t2(safe_increment);
t1.join();
t2.join();
std::cout << "main: " << g_i << '\n';
for (std::vector<int>::const_iterator i = test.begin(); i != test.end(); ++i)
std::cout << "main vector: " << *i << '\n';
}
Both std::thread execution threads, as well as the original main execution thread are invoking various methods of the same std::vector object.
None of std::vector's methods (or any of the C++ library containers' methods) are thread-safe, so all access to them from all execution threads must be sequenced (i.e. protected by a mutex). It doesn't matter whether the vector's contents are modified, or not. begin() is not thread safe. Full stop. Etc...
Adding insult to injury, resize() invalidates all existing iterators to the contents of a std::vector, so a resize() that gets executed by any of the std::threads will immediately invalidate all iterators to the same std::vector object in use by the other threads; and thusly the whole thing must be sequenced/locked.
TL;DR: you must use a mutex for any access to a std::vector. Whether the contents of the vector are modified, or not, by a particular execution thread, is immaterial.
P.S. The issue of std::vector methods not being thread safe is independent of the thread-safety of whatever's in the vector. If you already have all the iterators to the vector's contents ready, and start doing things to what's in the vector using the existing iterators in multiple execution threads: whether that requires sequencing depends on the inherent nature of whatever's in your vector, and its thread-safety requirements.

Why is my program printing garbage?

My code:
#include <iostream>
#include <thread>
void function_1()
{
std::cout << "Thread t1 started!\n";
for (int j=0; j>-100; j--) {
std::cout << "t1 says: " << j << "\n";
}
}
int main()
{
std::thread t1(function_1); // t1 starts running
for (int i=0; i<100; i++) {
std::cout << "from main: " << i << "\n";
}
t1.join(); // main thread waits for t1 to finish
return 0;
}
I create a thread that prints numbers in decreasing order while main prints in increasing order.
Sample output here. Why is my code printing garbage ?
Both threads are outputting at the same time, thereby scrambling your output.
You need some kind of thread synchronization mechanism on the printing part.
See this answer for an example using a std::mutex combined with std::lock_guard for cout.
It's not "garbage" — it's the output you asked for! It's just jumbled up, because you have used a grand total of zero synchronisation mechanisms to prevent individual std::cout << ... << std::endl lines (which are not atomic) from being interrupted by similar lines (which are still not atomic) in the other thread.
Traditionally we'd lock a mutex around each of those lines.