zoukankan      html  css  js  c++  java
  • C++11 多线程 教学(2)

     

    C++11开始支持多线程编程,之前多线程编程都需要系统的支持,在不同的系统下创建线程需要不同的API如pthread_create(),Createthread(),beginthread()等,使用起来都比较复杂,C++11提供了新头文件<thread>、<mutex>、<atomic>、<future>等用于支持多线程。

    使用C++11开启一个线程是比较简单的,下面来看一个简单的例子:

    #include <thread>

    #include <iostream>

     

    void hello()

    {

        std::cout << "Hello from thread " << std::endl;

    }

     

    int main()

    {

        std::thread t1(hello);

        t1.join();

    std::cout<<"Main Thread"<<std::endl;

        return 0;

    }

    运行结果:

    说明,通过thread 类直接申明一个线程t1,参数是这个线程执行的回调函数的地址,通过jion()方法阻塞主线程,直到t1线程执行结束为止。

             C++11支持Lambda表达式,因此一个新线程的回调函数也可以是有一个Lambda表达式的形式,但是注意如果使用Lambda表达式最好不要使用引用的方式,应该使用值传递的方式来访问数据,在多线程中使用引用容易造成混乱。下面这个例子稍微复杂,创建了多个子线程,并使用了get_id()方法来获取当前线程的id。

    #include <thread>

    #include <iostream>

    #include <vector>

     

    int main()

    {

        std::vector<std::thread> threads;

     

        for(int i = 0; i < 5; ++i){

            threads.push_back(std::thread([](){

                std::cout << "Hello from lamda thread " << std::this_thread::get_id() << std::endl;

            }));

        }

     

        for(auto& thread : threads){

            thread.join();

        }

     

        std::cout<<"Main Thread"<<" "<<std::this_thread::get_id()<<std::endl;

        return 0;

    }

    运行结果:

    上述代码中,使用vector来存放每个线程,线程的回调函数通过Lambda表达式产生,注意后面join的使用方式。

    可以通过sleep_for来使线程睡眠一定的时间:

    #include <thread>

    #include <iostream>

    #include <mutex>

    using namespace std;

     

    int main()

    {

        std::mutex m;

        thread t1([&m]()

        {

            std::this_thread::sleep_for (chrono::seconds(10)); 

            for(int i=0;i<10;i++) 

             {     

                m.lock(); 

                    cout <<  "In t1 ThreadID : " << std::this_thread::get_id() << ":" << i << endl;         

                m.unlock (); 

            } 

        } );

     

        thread t2([&m]() 

        {          

            std::this_thread::sleep_for (chrono::seconds(1)); 

            for(int i=0;i<10;i++) 

            {         

                m.lock (); 

                    cout <<  "In t2 ThreadID : " << std::this_thread::get_id() << ":" << i << endl;         

                m.unlock(); 

            } 

        } ); 

        t1.join();     

        t2.join();     

     

        cout<<"Main Thread"<<endl;

     

        return 0;

    }

    运行结果:

    可以看出,由于线程t1睡眠的时间较长,t2先执行了。

    延时有这几种类型:nanoseconds、microseconds、milliseconds、seconds、minutes、hours。

    在使用多线程的程序中操作共享数据的时候一定要小心,由于线程的乱序执行,可能会得到意想不到的结果。通过下面的程序来看:

    #include <thread>

    #include <iostream>

    #include <vector>

    #include <mutex>

     

    struct Counter {

        std::mutex mutex;

        int value;

     

        Counter() : value(0) {}

     

        void increment(){

           // mutex.lock();                【1】表示没有使用锁

            ++value;

           // mutex.unlock();              【1】

        }

     

        void decrement(){

            mutex.lock();

            --value;

            mutex.unlock();

        }

    };

     

    int main(){

        Counter counter;

     

        std::vector<std::thread> threads;

     

        for(int i = 0; i < 5; ++i){

            threads.push_back(std::thread([&](){

                for(int i = 0; i < 10000; ++i){

                    counter.increment();

                }

            }));

        }

     

        for(auto& thread : threads){

            thread.join();

        }

     

        std::cout << counter.value << std::endl;

     

        return 0;

    }

    运行结果:

    【1】

    运行结果:(使用了锁)

    说明:由于创建线程是使用lambda表达式,并使用引用的方式访问counter这个变量,当没有使用lock来保护的时候(情况【1】),执行的结果可能不像预期的5000(程序的意思是每个线程使counter中的value自加1000次,5个线程运行结束的时候应该是5000),当没有使用锁的时候自加的操作可能被其他线程打断,因此结果可能会小于5000。

  • 相关阅读:
    poj 1860 Currency Exchange(最短路径的应用)
    poj 2965 The Pilots Brothers' refrigerator
    zoj 1827 the game of 31 (有限制的博弈论)
    poj 3295 Tautology (构造法)
    poj 1753 Flip Game(枚举)
    poj 2109 (贪心)
    poj 1328(贪心)
    Qt 对单个控件美化
    Qt 4基础
    Bash Shell
  • 原文地址:https://www.cnblogs.com/lvdongjie/p/4487772.html
Copyright © 2011-2022 走看看