課時4 線程傳參詳解,detach()大坑,成員函數作線程函數

線程傳參

void myprint(int a)
{
    cout << "此時在子線程中" << endl;
    cout << "a = " << a  << endl;
}

int main(int argc, char** argv)
{
    int a = 1;

    thread myjob(myprint, a);

    cout << "此時在主線程中" << endl;
    return 0;
}

detach()的坑

  • 使用detach()時會有這麼一個問題:由於子線程與主線程分離了,若是子線程的可調用對象使用了main()裏的變量且主線程又先結束了,則會在子線程中就使用了根本不存在的東西,就會產生不可預測現象,尤爲是當可調用對象的參數爲引用或指針類型函數

  • 參數中有類的對象時,若是想經過隱式轉換傳入類對象極可能會出現錯誤,最好老老實實傳入類對象或構造好類對象傳入代碼中的std::this_thread::get_id()能夠得到線程IDthis

class A
{
public:
    A(int i):myi(i) { cout << "構造函數" << std::this_thread::get_id() << endl; }
    A(const A& a):myi(a.myi) { cout << "拷貝構造函數" << std::this_thread::get_id() << endl; }

    void operator()() { cout << "此時在子線程中" << std::this_thread::get_id() << endl; }

    ~A() { cout << "析構函數" << std::this_thread::get_id() << endl; }
private:
    int myi;
};

void myprint(const int& a, const A& b)
{
    cout << "此時在子線程中" << std::this_thread::get_id() << endl;
}

int main(int argc, char** argv)
{
    int a = 1;
    int& b = a;
    A c(a);
    thread myjob(myprint, a, c);
    //thread myjob(myprint, a, A(a));構造好類的臨時對象傳入
    //thread myjob(myprint, a, a);千萬不要有這種操做,碰上detach就完了,在打印出來的線程id中能夠看到將a轉換爲類的對象是在子線程中完成的,若是用了detach且主線程又先結束了,那就會使用一個不存在的變量

    myjob.join();

    cout << "此時在主線程中" << std::this_thread::get_id() << endl;
    return 0;
  • 當使用了引用傳遞(然而如今看來引用類型都必須是constthread仍是會用值傳遞的方式傳入可調用對象,好比上面的那個類,因此當在子線程中修改變量時主線程不會同步修改,此時加個std::ref()能夠解決,他就能夠真正的按引用傳遞的方式
class A
{
public:
...
    void change() const { myi = 199; }

private:
    mutable int myi;
};

void myprint(const int& a, const A& b)
{
    b.change();
    cout << "此時在子線程中" << std::this_thread::get_id() << endl;
}

int main(int argc, char** argv)
{
    int a = 1;
    int& b = a;
    A c(a);
    thread myjob(myprint, a, std::ref(c));

    myjob.join();

    cout << "此時在主線程中" << std::this_thread::get_id() << endl;
    return 0;

一些其餘的線程入口

  • unique_ptr類型智能指針傳遞需使用std::move()
void myprint(unique_ptr<int> a)
{
    cout << *a << endl;
    cout << "此時在子線程中" << std::this_thread::get_id() << endl;
}

int main(int argc, char** argv)
{
    unique_ptr<int> d(new int(100));
    thread myjob(myprint, std::move(d));
  • 使用成員函數做爲可調用對象
void change(int ab) { cout << ab << "此時在子線程中" << std::this_thread::get_id() << endl; }

    int a = 1;
    int& b = a;
    A c(a);
    thread myjob(&A::change, c, 100);
  • 用類做爲可調用對象且有參數的狀況
void operator()(int ab) { cout << ab << "此時在子線程中" << endl; }

    A a;
    thread myjob(a, 100);
相關文章
相關標籤/搜索