C++多线程编程第九讲--future其他成员函数、shared_future、atomic

//(1)std::future的其他成员函数

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

using namespace std;

int my_thread()
{
    cout << "my_thread start...  " << "thread id = " << this_thread::get_id() << endl;
    std::chrono::milliseconds duro(5000);
    std::this_thread::sleep_for(duro);
    cout << "my_thread end...  " << "thread id = " << this_thread::get_id() << endl;
    return 5;
}

int main()
{
    cout << "main() start... " << "thread id = " << std::this_thread::get_id() << endl;
    std::future<int> result = std::async(my_thread);
    std::future_status status = result.wait_for(std::chrono::milliseconds(6000));  //等待
    if (status == std::future_status::timeout)
    {
        //超时表示等待的线程还没有执行结束
        cout << "overtime..." << endl;
    }
    else if (status == std::future_status::ready)
    {
        cout << "ready..." << endl;
    }
    else if (status == std::future_status::deferred)  //线程还没开始执行
    {
        cout << "deferred..." << endl;           //对应async中第一个参数中的std::launch::deferred
    }

    cout << result.get() << endl;              //主线程会在get这里一致等到新的线程返回结果 
    cout << "main() end... " << "thread id = " << std::this_thread::get_id() << endl;
    return 0;
}

//(2)std::shared_future
// 是一个类模板,他的get函数就不是转移了,而是复制。
// 
// 如以下程序,只能在线程2中调用get,如果还有其他线程想要线程1返回的结果再次调用get的时候
// 程序就会报错
#include<iostream>
#include<mutex>
#include<thread>
#include<future>

using namespace std;

int my_thread(int mypar)
{
    cout << "my_thread start...  " << "thread id = " << this_thread::get_id() << endl;
    std::chrono::milliseconds duro(5000);
    std::this_thread::sleep_for(duro);
    cout << "my_thread end...  " << "thread id = " << this_thread::get_id() << endl;
    return mypar;
}

void my_thread2(std::future<int>& fut)
{
    cout << "my_thread2 start..." << "thread id = " << this_thread::get_id() << endl;
    //程序运行到这里,即便线程1还没有执行结束,调用get也会等待线程1返回结果再运行
    cout << "fut.get() = " << fut.get() << endl;  //打印返回的结果,get函数设计是一个移动语义,所以不能调用两次。
    cout << "my_thread2 end..." << "thread id = " << this_thread::get_id() << endl;
}

int main()
{
    cout << "main() start... " << "thread id = " << std::this_thread::get_id() << endl;

    std::packaged_task<int(int)> mypt(my_thread);           //把函数my_thread包装起来
    std::thread t1(std::ref(mypt), 5);                      //用一个package_task对象作为线程的参数

    std::future<int> result = mypt.get_future();

    //std::shared_future<int> s_fut(std::move(result));    //使用右值


    std::thread t2(my_thread2, std::ref(result));     //future对象不能拷贝,所以只能以std::ref的方式进行传递
    t2.join();
    t1.join();
    cout << "main() end... " << "thread id = " << std::this_thread::get_id() << endl;
    return 0;
}

// 则使用shared_future避免以上的情况

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

using namespace std;

int my_thread(int mypar)
{
    cout << "my_thread start...  " << "thread id = " << this_thread::get_id() << endl;
    std::chrono::milliseconds duro(5000);
    std::this_thread::sleep_for(duro);
    cout << "my_thread end...  " << "thread id = " << this_thread::get_id() << endl;
    return mypar;
}

void my_thread2(std::shared_future<int>& s_fut)
{
    cout << "my_thread2 start..." << "thread id = " << this_thread::get_id() << endl;
    //程序运行到这里,即便线程1还没有执行结束,调用get也会等待线程1返回结果再运行
    cout << "fut.get() = " << s_fut.get() << endl;  //get只是复制,可以调用多次
    cout << "my_thread2 end..." << "thread id = " << this_thread::get_id() << endl;
}

void my_thread3(std::shared_future<int>& s_fut)
{
    cout << "my_thread3 start..." << "thread id = " << this_thread::get_id() << endl;
    //程序运行到这里,即便线程1还没有执行结束,调用get也会等待线程1返回结果再运行
    cout << "fut.get() = " << s_fut.get() << endl;  //get只是复制,可以调用多次
    cout << "my_thread3 end..." << "thread id = " << this_thread::get_id() << endl;
}

int main()
{
    cout << "main() start... " << "thread id = " << std::this_thread::get_id() << endl;

    std::packaged_task<int(int)> mypt(my_thread);           //把函数my_thread包装起来
    std::thread t1(std::ref(mypt), 5);                      //用一个package_task对象作为线程的参数

    std::future<int> result = mypt.get_future();

    //bool value = result.valid();  //可以用来判断result中是否有有效值 

    std::shared_future<int> s_fut(std::move(result));    //使用右值
    //std::shared_future<int> s_fut(result.share());    //使用右值,两种写法都可以

    std::thread t2(my_thread2, std::ref(s_fut));     //future对象不能拷贝,所以只能以std::ref的方式进行传递
    std::thread t3(my_thread3, std::ref(s_fut));     //future对象不能拷贝,所以只能以std::ref的方式进行传递
    t2.join();
    t1.join();
    t3.join();
    cout << "main() end... " << "thread id = " << std::this_thread::get_id() << endl;
    return 0;
}

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

using namespace std;

int my_thread(int mypar)
{
    cout << "my_thread start...  " << "thread id = " << this_thread::get_id() << endl;
    std::chrono::milliseconds duro(5000);
    std::this_thread::sleep_for(duro);
    cout << "my_thread end...  " << "thread id = " << this_thread::get_id() << endl;
    return mypar;
}

void my_thread2(std::shared_future<int>& s_fut)
{
    cout << "my_thread2 start..." << "thread id = " << this_thread::get_id() << endl;
    //程序运行到这里,即便线程1还没有执行结束,调用get也会等待线程1返回结果再运行
    cout << "fut.get() = " << s_fut.get() << endl;  //get只是复制,可以调用多次
    cout << "my_thread2 end..." << "thread id = " << this_thread::get_id() << endl;
}

void my_thread3(std::shared_future<int>& s_fut)
{
    cout << "my_thread3 start..." << "thread id = " << this_thread::get_id() << endl;
    //程序运行到这里,即便线程1还没有执行结束,调用get也会等待线程1返回结果再运行
    cout << "fut.get() = " << s_fut.get() << endl;  //get只是复制,可以调用多次
    cout << "my_thread3 end..." << "thread id = " << this_thread::get_id() << endl;
}

int main()
{
    cout << "main() start... " << "thread id = " << std::this_thread::get_id() << endl;

    std::packaged_task<int(int)> mypt(my_thread);           //把函数my_thread包装起来
    std::thread t1(std::ref(mypt), 5);                      //用一个package_task对象作为线程的参数

    //bool value = result.valid();  //可以用来判断result中是否有有效值 

    std::shared_future<int> s_fut(mypt.get_future());    //使用右值
    //std::shared_future<int> s_fut(result.share());    //使用右值,两种写法都可以

    std::thread t2(my_thread2, std::ref(s_fut));     //future对象不能拷贝,所以只能以std::ref的方式进行传递
    std::thread t3(my_thread3, std::ref(s_fut));     //future对象不能拷贝,所以只能以std::ref的方式进行传递
    t2.join();
    t1.join();
    t3.join();
    cout << "main() end... " << "thread id = " << std::this_thread::get_id() << endl;
    return 0;
}

//(3)原子操作std::atomic
	//(3.1)原子操作概念引出范例

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

using namespace std;

int g_mycount = 0;
mutex g_my_mutex;

void my_thread()
{
    int i = 0;
    for (; i < 1000000; ++i)
    {
        g_my_mutex.lock();          //防止++的执行被打断
        g_mycount++;
        g_my_mutex.unlock();
    }
}


int main()
{
    cout << "main() start... " << "thread id = " << std::this_thread::get_id() << endl;

    thread mythread(my_thread);

    thread mythread2(my_thread);

    mythread.join();
    mythread2.join();   

    cout << g_mycount << endl;  
    cout << "main() end... " << "thread id = " << std::this_thread::get_id() << endl;
    return 0;
}

// 但是以上的程序效率太低,原子操作也会有相同的作用。互斥量的加锁针对的是一个代码段,而原子操作
// 针对的是一个变量。原子操作用于统计功能等。

//(3.2)基本的std::atomic用法范例
  #include<iostream>
    #include<mutex>
    #include<thread>
    #include<future>
    
    using namespace std;
    
    
    //int g_mycount = 0;
    std::atomic<int> g_mycount = 0;   //具备原子操作的整型值
    
    void my_thread()
    {
        int i = 0;
        for (; i < 1000000; ++i)
        {
            g_mycount++;
        }
    }
    
    
    int main()
    {
        cout << "main() start... " << "thread id = " << std::this_thread::get_id() << endl;
    
        thread mythread(my_thread);
    
        thread mythread2(my_thread);
    
        mythread.join();
        mythread2.join();
    
        cout << g_mycount << endl;
        cout << "main() end... " << "thread id = " << std::this_thread::get_id() << endl;
        return 0;
    }
     
     
     #include<iostream>
    #include<mutex>
    #include<thread>
    #include<future>
    
    using namespace std;
    
    
    //int g_mycount = 0;
    std::atomic<bool> g_ifend = false;
    
    void my_thread()
    {
        std::chrono::milliseconds dura(1000); //
    
        while (g_ifend == false)
        {
            cout << "my_thread id = " << std::this_thread::get_id() << endl;
            std::this_thread::sleep_for(dura);
        }
    }
    
    int main()
    {
        cout << "main() start... " << "thread id = " << std::this_thread::get_id() << endl;
    
        thread mythread(my_thread);
    
        thread mythread2(my_thread);
    
        std::chrono::milliseconds dura(5000); //
        std::this_thread::sleep_for(dura);
    
        g_ifend = true;
    
        mythread.join();
        mythread2.join();
    
        cout << "main() end... " << "thread id = " << std::this_thread::get_id() << endl;
        return 0;
    }

  

上一篇:一篇文章搞懂 CompletionService


下一篇:CompletableFuture异步和线程池讲解