C++11多线程编程 第三章: 如何向线程传参

C++11 Multithreading – Part 3: Carefully Pass Arguments to Threads

Varun January 22, 2015 C++11 Multithreading – Part 3: Carefully Pass Arguments to Threads2018-08-18T15:14:54+00:00C++ 11c++11 ThreadsMultithreading 1 Comment

To Pass arguments to thread’s associated callable object or function just pass additional arguments to the std::thread constructor.
By default all arguments are copied into the internal storage of new thread.

Lets look at an example

Passing simple arguments to a std::thread in C++11

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

#include <iostream>

#include <string>

#include <thread>

void threadCallback(int x, std::string str)

{

    std::cout<<"Passed Number = "<<x<<std::endl;

    std::cout<<"Passed String = "<<str<<std::endl;

}

int main()  

{

    int x = 10;

    std::string str = "Sample String";

    std::thread threadObj(threadCallback, x, str);

    threadObj.join();

    return 0;

}

How not to pass arguments to threads in C++11

Don’t pass addresses of variables from local stack to thread’s callback function. Because it might be possible that local variable in Thread 1 goes out of scope but Thread 2 is still trying to access it through it’s address.
In such scenario accessing invalid address can cause unexpected behaviour.
For example,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

#include <iostream>

#include <thread>

void newThreadCallback(int * p)

{

    std::cout<<"Inside Thread :  "" : p = "<<p<<std::endl;

    std::chrono::milliseconds dura( 1000 );

    std::this_thread::sleep_for( dura );

    *p = 19;

}

void startNewThread()

{

    int i = 10;

    std::cout<<"Inside Main Thread :  "" : i = "<<i<<std::endl;

    std::thread t(newThreadCallback,&i);

    t.detach();

    std::cout<<"Inside Main Thread :  "" : i = "<<i<<std::endl;

}

int main()

{

    startNewThread();

    std::chrono::milliseconds dura( 2000 );

    std::this_thread::sleep_for( dura );

    return 0;

}

Similarly be careful while passing pointer to memory located on heap to thread. Because it might be possible that some thread deletes that memory before new thread tries to access it.
In such scenario accessing invalid address can cause unexpected behaviour.
For example,

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>

void newThreadCallback(int * p)

{

    std::cout<<"Inside Thread :  "" : p = "<<p<<std::endl;

    std::chrono::milliseconds dura( 1000 );

    std::this_thread::sleep_for( dura );

    *p = 19;

}

void startNewThread()

{

    int * p = new int();

    *p = 10;

    std::cout<<"Inside Main Thread :  "" : *p = "<<*p<<std::endl;

    std::thread t(newThreadCallback,p);

    t.detach();

    delete p;

    p = NULL;

}

int main()

{

    startNewThread();

    std::chrono::milliseconds dura( 2000 );

    std::this_thread::sleep_for( dura );

    return 0;

}

How to pass references to std::thread in C++11

As arguments are copied to new threads stack so, if you need to pass references in common way i.e.

Check this,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

#include <iostream>

#include <thread>

void threadCallback(int const & x)

{

    int & y = const_cast<int &>(x);

    y++;

    std::cout<<"Inside Thread x = "<<x<<std::endl;

}

int main()

{

    int x = 9;

    std::cout<<"In Main Thread : Before Thread Start x = "<<x<<std::endl;

    std::thread threadObj(threadCallback, x);

    threadObj.join();

    std::cout<<"In Main Thread : After Thread Joins x = "<<x<<std::endl;

    return 0;

}

Its output is

In Main Thread : Before Thread Start x = 9 
Inside Thread x = 10 
In Main Thread : After Thread Joins x = 9 

Even if threadCallback accepts arguments as reference but still changes done it are not visible outside the thread.
Its because x in the thread function threadCallback is reference to the temporary value copied at the new thread’s stack.

How to fix this ?

Using std::ref() i.e.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

#include <iostream>

#include <thread>

void threadCallback(int const & x)

{

    int & y = const_cast<int &>(x);

    y++;

    std::cout<<"Inside Thread x = "<<x<<std::endl;

}

int main()

{

    int x = 9;

    std::cout<<"In Main Thread : Before Thread Start x = "<<x<<std::endl;

    std::thread threadObj(threadCallback,std::ref(x));

    threadObj.join();

    std::cout<<"In Main Thread : After Thread Joins x = "<<x<<std::endl;

    return 0;

}

Its output is

In Main Thread : Before Thread Start x = 9 
Inside Thread x = 10 
In Main Thread : After Thread Joins x = 10 
 

Assigning pointer to member function of a class as thread function:

Pass the pointer to member function as callback function and pass pointer to Object as second argument.

For example,

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

#include <iostream>

#include <thread>

class DummyClass {

public:

    DummyClass()

    {}

    DummyClass(const DummyClass & obj)

    {}

    void sampleMemberFunction(int x)

    {

        std::cout<<"Inside sampleMemberFunction "<<x<<std::endl;

    }

};

int main() {

    DummyClass dummyObj;

    int x = 10;

    std::thread threadObj(&DummyClass::sampleMemberFunction,&dummyObj, x);

    threadObj.join();

    return 0;

}

通过这种方式, 就可以模拟Java中的Thread函数. 类似:

class MyThread{

void stop(); //里面标记一个原子变量_stop;

void run(); // 在循环里判断_stop是否置为true, 如果为true, 则停止执行.

void start(){

       std::thread myThread(&MyThread::run, this); //创建子线程执行run函数.
        if (myThread.joinable()) {
           myThread.detach(); // 与创建函数的对象分离, 否则对象析构时, 会调用线程的terminate终止线程执行. 
        }

    }

}

猜你喜欢

转载自blog.csdn.net/u201011221/article/details/83716790