Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Errors with multithreading in for loop

I am trying to add a simple for loop with threads, yet still something is not working out. I've checked a number of reasons and I cannot find any solution to that.

I have a simple class with two methods A() and B(). From the other class, I'm calling method A(). This is how it looks:

void MyClass::A()
{
    std::vector<std::thread> threads;
    for(int i=0;i<2;i++)
    {
        threads.push_back(std::thread(&MyClass::B, this));
    }
    for(auto &t : threads)
    {
        if(t.joinable())
            t.join();
    }
}

void MyClass::B()
{
}

And yet I am still receiving some errors:

#0 ??   ?? () (??:??)
#1 00446D62 pthread_create_wrapper () (??:??)
#2 75327FB0 msvcrt!_cexit() (C:\Windows\SysWOW64\msvcrt.dll:??)
#3 040C8710 ?? () (??:??)
#4 753280F5 msvcrt!_beginthreadex() (C:\Windows\SysWOW64\msvcrt.dll:??)
#5 75B17C04 KERNEL32!BaseThreadInitThunk() (C:\Windows\SysWOW64\kernel32.dll:??)
#6 77ABAB8F ?? () (??:??)
#7 77ABAB5A ?? () (??:??)
#8 ??   ?? () (??:??)

Does someone have any idea what is wrong?

Just to add one more thing. This:

void MyClass::A()
{
    std::thread t(&MyClass::B, this);
    if(t.joinable())
        t.join();
}

void MyClass::B()
{
}

works without any problems.

like image 858
sebap123 Avatar asked Feb 25 '16 15:02

sebap123


People also ask

What is some issues with multithreading?

Complications due to Concurrency − It is difficult to handle concurrency in multithreaded processes. This may lead to complications and future problems. Difficult to Identify Errors− Identification and correction of errors is much more difficult in multithreaded processes as compared to single threaded processes.

What will happen if multiple threads accessing the same resource?

Multiple threads accessing shared data simultaneously may lead to a timing dependent error known as data race condition. Data races may be hidden in the code without interfering or harming the program execution until the moment when threads are scheduled in a scenario (the condition) that break the program execution.

Can STD thread fail?

std::thread::join() is permitted to fail, throwing a std::system_error for no_such_process if the thread is "not valid". Note that the no_such_process case is distinct from a thread that is not joinable (for which the error code is invalid_argument ).


1 Answers

I would suggest using new and a pointer instead of references.

While references are nice, the number of comments illustrate the confusion caused in this case. How can you prove that the third party library implementation (eg. std) will work the way you are expecting it to? and across platforms?

If you use:

std::vector<std::thread *> threads;

and:

threads.push_back(new std::thread(&MyClass::B(), this));

And of course with a 'delete' when you are done with the thread, then the confusion is eliminated.

Also, the code is loading the SAME instance of the 'A' class onto the array for all threads. If you use member variables in A within function 'B', without any sort of multithread protection (eg semaphores, critical sections, etc) your code will never work correctly. Using a 'new' for the thread instance creation avoids the problems that copy constructors or assignment operators cause with the vector class.

#include <SDKDDKVer.h>
#include <vector>
#include <thread>
#include <iostream>

using namespace std;

class MyClass {
  public:
    void A() {
      cout << "starting\n";
      cout << "creating threads\n";
      vector<thread*> threads;
      for (int i = 0;i<4;i++) {
        thread * t = new thread(&MyClass::B, this);
        cout << "creating thread "<<t<<" id:"<<t->get_id()<<"\n";
        threads.push_back(t);
      }
      cout << "waiting for threads to complete\n";
      for (thread * t : threads) {
        if (t->joinable()) {
          t->join();
        }
        cout << "destroying "<<t<<"\n";
        delete t;
      }
      cout << "done\n";
   }

   void B() {
     // now it would be very bad if this function used 
     // member variables that are part of this instance of A
     cout << "hello from " << this << "\n";
   }
}; 

int main() {
  MyClass cls;
  cls.A();
  return 0;
}
like image 150
kgorham Avatar answered Oct 22 '22 05:10

kgorham