zoukankan      html  css  js  c++  java
  • C++11 多线程

    C++ 11中的多线程技术

    C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是 <atomic> ,<thread>,<mutex>,<condition_variable><future>

    • <atomic>:提供原子操作功能,该头文主要声明了两个类, std::atomic 和 std::atomic_flag,另外还声明了一套 C 风格的原子类型和与 C 兼容的原子操作的函数。

    • <thread>:线程模型封装,该头文件主要声明了 std::thread 类,另外 std::this_thread 命名空间也在该头文件中。

    • <mutex>:互斥量封装,该头文件主要声明了与互斥量(mutex)相关的类,包括 std::mutex 系列类,std::lock_guard, std::unique_lock, 以及其他的类型和函数。

    • <condition_variable>:条件变量,该头文件主要声明了与条件变量相关的类,包括 std::condition_variable 和 std::condition_variable_any。

    • <future>:实现了对指定数据提供者提供的数据进行异步访问的机制。该头文件主要声明了 std::promise, std::package_task 两个 Provider 类,以及 std::future 和 std::shared_future 两个 Future 类,另外还有一些与之相关的类型和函数,std::async() 函数就声明在此头文件中。

    简单示例:

    #include <iostream>
    #include <thread>
    using namespace std;
    void thread_1()
    {
        cout << "hello from thread_1" << endl;
    }
    int main(int argc, char **argv)
    {
        thread t1(thread_1);
        /**
        join()相当于调用了两个函数:WaitForSingleObject、CloseHandle,事实上,在vc12中也是这么实现的
        */
        t1.join();
        return 0;
    }
    View Code

    注意事项

    1. 若线程调用到的函数在一个类中,则必须将该函数声明为静态函数函数

    因为静态成员函数属于静态全局区,线程可以共享这个区域,故可以各自调用

     #include <iostream>  
        #include <pthread.h>  
          
        using namespace std;  
          
        #define NUM_THREADS 5  
          
        class Hello  
        {  
        public:  
            //多线程调用,声明为static
            static void* say_hello( void* args )  
            {  
                cout << "hello..." << endl;  
            }  
        };  
          
        int main()  
        {  
            pthread_t tids[NUM_THREADS];  
            for( int i = 0; i < NUM_THREADS; ++i )  
            {  
                int ret = pthread_create( &tids[i], NULL, Hello::say_hello, NULL );  
                if( ret != 0 )  
                {  
                    cout << "pthread_create error:error_code" << ret << endl;  
                }  
            }  
            pthread_exit( NULL );  
        }  
    View Code

    测试结果:

       
        hello...  
        hello...  
        hello...  
        hello...  
        hello... 
    View Code

    1. 代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。

    2. 线程创建时属性参数的设置pthread_attr_t及join功能的使用
      线程的属性由结构体pthread_attr_t进行管理。

    typedef struct
    {
        int      detachstate;       //线程的分离状态
        int      schedpolicy;       //线程调度策略
        struct sched_param   schedparam;   //线程的调度参数
        int inheritsched;       //线程的继承性 
        int scope;              //线程的作用域 
        size_t guardsize;   //线程栈末尾的警戒缓冲区大小 
        int stackaddr_set; 
        void * stackaddr;   //线程栈的位置 
        size_t stacksize;   // 线程栈的大小
    }pthread_attr_t;

    示例:

     #include <iostream>  
        #include <pthread.h>  
          
        using namespace std;  
          
        #define NUM_THREADS 5  
          
        void* say_hello( void* args )  
        {  
            cout << "hello in thread " << *(( int * )args) << endl;  
            int status = 10 + *(( int * )args); //线程退出时添加退出的信息,status供主程序提取该线程的结束信息  
            pthread_exit( ( void* )status );   
        }  
          
        int main()  
        {  
            pthread_t tids[NUM_THREADS];  
            int indexes[NUM_THREADS];  
              
            pthread_attr_t attr; //线程属性结构体,创建线程时加入的参数  
            pthread_attr_init( &attr ); //初始化  
            pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); //是设置你想要指定线程属性参数,这个参数表明这个线程是可以join连接的,join功能表示主程序可以等线程结束后再去做某事,实现了主程序和线程同步功能  
            for( int i = 0; i < NUM_THREADS; ++i )  
            {  
                indexes[i] = i;  
                int ret = pthread_create( &tids[i], &attr, say_hello, ( void* )&( indexes[i] ) );  
                if( ret != 0 )  
                {  
                cout << "pthread_create error:error_code=" << ret << endl;  
            }  
            }   
            pthread_attr_destroy( &attr ); //释放内存   
            void *status;  
            for( int i = 0; i < NUM_THREADS; ++i )  
            {  
            int ret = pthread_join( tids[i], &status ); //主程序join每个线程后取得每个线程的退出信息status  
            if( ret != 0 )  
            {  
                cout << "pthread_join error:error_code=" << ret << endl;  
            }  
            else  
            {  
                cout << "pthread_join get status:" << (long)status << endl;  
            }  
            }  
        }  
    View Code

    测试结果:

    hello in thread hello in thread 1hello in thread 3
    hello in thread 4
    0
    hello in thread 2
    pthread_join get status:10
    pthread_join get status:11
    pthread_join get status:12
    pthread_join get status:13
    pthread_join get status:14
    View Code
  • 相关阅读:
    BZOJ 3924 / Luogu P3345 [ZJOI2015]幻想乡战略游戏 (动态点分治/点分树)
    BZOJ 3065 带插入区间K小值 (替罪羊树套线段树)
    BZOJ 3217: ALOEXT (块状链表套trie)
    BZOJ 3514: Codechef MARCH14 GERALD07加强版 (LCT维护最大生成树+主席树)
    BZOJ 3932: [CQOI2015]任务查询系统 (主席树板题)
    BZOJ 3658: Jabberwocky (双向链表+BIT)
    BZOJ 1180 [CROATIAN 2009]OTOCI // BZOJ 2843 极地旅行社 // Luogu P4321 [COCI 2009] OTOCI / 极地旅行社 (LCA板题)
    BZOJ 2759 一个动态树好题 (LCT)
    BZOJ 2244: [SDOI2011]拦截导弹 (CDQ分治 三维偏序 DP)
    codefroces 612E Square Root of Permutation
  • 原文地址:https://www.cnblogs.com/52why/p/7629290.html
Copyright © 2011-2022 走看看