1. 程式人生 > >C++多線程編程二

C++多線程編程二

hang int ftime 答案 tro 類型 情況下 根據 diff

1. 死鎖與解鎖:

#include <iostream>
#include <thread>
#include <mutex>

using namespace std;

//thread引用類型函數,模板,避免類型轉換,盡量指針,引用
//鎖住一個變量之後,盡快操作完解鎖,不要再鎖,否則互鎖
#define COUNT 100000
mutex g_mutex1, g_mutex2;//互斥量

void add1(int *p1, int *p2)
{
    for (int i = 0; i < COUNT; i++)
    {
        /*g_mutex1.lock();
        p1++;
        g_mutex2.lock();
        p2++;
        g_mutex1.unlock();
        g_mutex2.unlock();
*/ g_mutex1.lock(); (*p1)++; g_mutex1.unlock(); g_mutex2.lock(); (*p2)++; g_mutex2.unlock(); } } void add2(int *p1, int *p2) { for (int i = 0; i < COUNT; i++) { /*g_mutex2.lock(); g_mutex1.lock(); p1++; g_mutex1.unlock(); p2++; g_mutex2.unlock();
*/ g_mutex2.lock(); (*p2)++; g_mutex2.unlock(); g_mutex1.lock(); (*p1)++; g_mutex1.unlock(); } } void main() { int a = 0; int b = 0; thread th1(add1, &a, &b); thread th2(add2, &a, &b); th1.join(); th2.join();
while (1) { cout << a << endl; cout << b << endl; this_thread::sleep_for(chrono::seconds(1)); } cin.get(); }

2. 迅雷面試題:

  編寫一個程序,開啟3個線程,這3個線程的ID分別為A、B、C,每個線程將自己的ID在屏幕上打印10遍,

  要求輸出結果必須按ABC的順序顯示。如:ABCABC...,依次遞推。

    【參考答案】

//編寫一個程序,開啟3個線程,這3個線程的ID分別為A、B、C,每個線程將自己的ID在屏幕上打印10遍,
//要求輸出結果必須按ABC的順序顯示。如:ABCABC...,依次遞推。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

using namespace std;

int LOOP = 10;    //循環次數
int flag = 0;    //標識符 012012012012
mutex m;
condition_variable cv;

void fun(int id)
{
    for (int i = 0; i < LOOP; i++)
    {
        unique_lock<mutex> ulk(m);        //設定鎖定
        while ((id-65) != flag)
        {
            cv.wait(ulk);                //不是該出現的場合,就等待
        }
        cout << (char)id;                //轉換id

        flag = (flag + 1) % 3;            //012,012,012,...
        cv.notify_all();                //通知全部
    }
}

void main()
{
    thread t1(fun, 65);
    thread t2(fun, 66);
    thread t3(fun, 67);

    t1.join();
    t2.join();
    t3.join();

    cin.get();
}

    運行結果:技術分享圖片

    【分析】若題目變為:4個線程,輸出結果要求為: ABCDABCDABCD...又該如何做呢?

//編寫一個程序,開啟3個線程,這3個線程的ID分別為A、B、C,每個線程將自己的ID在屏幕上打印10遍,
//要求輸出結果必須按ABC的順序顯示。如:ABCABC...,依次遞推。

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

using namespace std;

int LOOP = 10;    //循環次數
int flag = 0;    //標識符 012012012012
mutex m;
condition_variable cv;

void fun(int id)
{
    for (int i = 0; i < LOOP; i++)
    {
        unique_lock<mutex> ulk(m);        //設定鎖定
        while ((id-65) != flag)
        {
            cv.wait(ulk);                //不是該出現的場合,就等待
        }
        cout << (char)id;                //轉換id

        flag = (flag + 1) % 4;            //012,012,012,...
        cv.notify_all();                //通知全部
    }
}

void main()
{
    thread t1(fun, 65);
    thread t2(fun, 66);
    thread t3(fun, 67);
    thread t4(fun, 68);

    t1.join();
    t2.join();
    t3.join();
    t4.join();

    cin.get();
}

    運行結果:技術分享圖片

3. 思考:上題中若變為開啟5個線程,ID分別為1,2,3,4,5,每個線程將自己的ID在屏幕上打印10遍,要求輸出結果為:12345,54321,12345,54321,...依此類推。

4. 線程交換 swap:

#include <iostream>
#include <thread>
using namespace std;

void main()
{
    thread t1([]() {cout << "ZhangShan"<<endl; });
    thread t2([]() {cout << "LiSi"<<endl; });

    cout << "t1.get_id():" << t1.get_id() << "    t2.get_id():" << t2.get_id() << endl;

    swap(t1, t2);    //交換句柄

    cout << "t1.get_id():" << t1.get_id() << "    t2.get_id():" << t2.get_id() << endl;

    t1.join();
    t2.join();

    cin.get();
}

5. 線程移動 move:

#include <iostream>
#include <thread>
#include <cstdlib>

using namespace std;

void main()
{
    thread t1([]() 
    {
        int i = 0;
        while (1)
        {
            i++;
            if (i > 1000000000)
            {
                break;
            }
        }
        cout << i << endl;
        system("pause");
    });
    
    cout << "t1:" << t1.get_id() << endl;    //6872
    //t1.join();
    thread t2 = move(t1);//線程移動,t2具備了t1的屬性,t1掛了
    cout << "t1:" << t1.get_id() << endl;    //0
    cout << "t2:" << t2.get_id() << endl;    //6872

    t2.join();

    cin.get();
}

    運行結果:技術分享圖片

6. 線程自動加解鎖:

#include <iostream>
#include <thread>
#include <mutex>

using namespace std;

#define N 10000000
mutex g_mutex;//全局互斥量

void add(int *p)
{
    for (int i = 0; i < N; i++)
    {
        unique_lock<mutex> ulk(g_mutex);
        //沒有mutex所有權,自動加鎖自動解鎖,根據塊語句鎖定
        //根據mutex屬性來決定,是否可以加鎖

        //lock_guard<mutex> lgd(g_mutex);    
        //擁有mutex所有權,自動加鎖自動解鎖
        //讀取mutex失敗的情況下就會一直等待
        (*p)++;
    }
}

void main()
{
    int a = 0;

    thread t1(add, &a);
    thread t2(add, &a);

    t1.join();
    t2.join();

    cout << a << endl;

    cin.get();
}

7. 線程等待固定時間:

#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <cstdlib>
#include <ctime>

using namespace std;

condition_variable cv;
mutex m;
bool done=false;

void run()
{
    auto start = chrono::high_resolution_clock::now();    //當前時間
    auto end = start + chrono::seconds(3);

    unique_lock<mutex> ulk(m);
    while (!done)
    {
        if (cv.wait_until(ulk, end) == cv_status::timeout)//超時
        {
            done = true;
            break;
        }
    }
    //this_thread::sleep_until(end);

    system("pause");
}

void main1601()
{
    thread th(run);

    cin.get();
}

void main()
{
    time_t t1, t2;
    auto start = chrono::high_resolution_clock::now();    //當前時間
    t1 = time(&t1);

    double db = 0;
    for (int i = 0; i < 1000000000; i++)
    {
        db += i;
    }

    auto end = chrono::high_resolution_clock::now();    //當前時間
    t2 = time(&t2);

    cout << (end - start).count() << endl;    //10^-9秒(ns)
    cout << difftime(t2, t1) << endl;

    cin.get();
}

C++多線程編程二