close up photo of programming of codes

codecungnhau.com

Một trang web về kỹ thuật lập trình

C++11 Multithreading – P.3: Truyền đối số cho Thread

Để truyền đối số cho đối tượng hoặc hàm liên kết với thread, chỉ cần truyền đối số bổ sung cho hàm tạo std::thread. Theo mặc định, tất cả các đối số được sao chép vào bộ nhớ trong của thread mới.

Truyền các đối số đơn giản cho std::thread

#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;
}

Làm thế nào để không truyền đối số cho thread

Đừng truyền địa chỉ của các biến từ local stack cho hàm callback của thread. Bởi vì có khả năng biến cục bộ trong thread 1 sẽ đi ra khỏi scope của nó, nhưng thread 2 lại đang cố gắng truy cập vào vùng địa chỉ đó. Tình huống này có thể tạo ra những hành vi không mong muốn. Ví dụ,

#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;
}

Tương tự như vậy, cẩn thận trong khi truyeenf con trỏ đến vùng nhớ nằm trên heap đến thread. Bởi vì có thể một số thread sẽ xóa bộ nhớ đó trước khi thread mới cố gắng truy cập nó. Trong trường hợp như vậy truy cập địa chỉ không hợp lệ có thể gây ra hành vi không ngờ. Ví dụ,

#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;
}

Cách để truyền tham chiếu đến thread

Nếu muốn truyền theo cách tham chiếu, các đối số sẽ được sao chép đến stack của thread.

#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;
}

Kết quả là:

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

Ngay cả khi threadCallback chấp nhận các đối số tham chiếu và thay đổi vẫn được thực hiện nhưng nó không hiển thị bên ngoài thread. Bởi vì x trong thread threadCallback được tham chiếu đến giá trị tạm thời được sao chép tại stack của thread mới.

Sử dụng std::ref() để fix vấn đề trên.

#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;
}

Kết quả là:

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

Gán con trỏ cho hàm thành viên của lớp là hàm thread

Truyền con trỏ đến hàm thành viên dưới dạng hàm gọi lại và truyền con trỏ tới đối tượng làm đối số thứ hai.

#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;
}

Đã đăng vào

trong

,

bởi

Bình luận

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *