博客專欄

        EEPW首頁 > 博客 > C++ 在類里面使用多線程技術

        C++ 在類里面使用多線程技術

        發布人:電子禪石 時間:2022-01-05 來源:工程師 發布文章

        C++ 在類里面使用多線程技術

        前言

        有很多時候,我們希望可以在C++類里面對那些比較耗時的函數使用多線程技術,但是熟悉C++對象語法的人應該知道,C++類的成員函數的函數指針不能直接做為參數傳到pthread_create,主要因為是C++成員函數指針帶有類命名空間,同時成員函數末尾是會被C++編譯器加上可以接收對象地址的this指針參數。因此需要將成員函數做一定的轉化,將其轉化為不被編譯器加上this指針,而由我們自己來為該函數維護”this”指針即可。

        舉例:

        #include <stdio.h>
        #include <stdlib.h>
        #include <iostream>
        #include <time.h>
        using namespace std;
        class Test
        {
            public:
                int sum=0;
                int cnt;
            public:
                int insert();
        };
        int Test::insert()
        {
            sleep(2);
            cnt+=1;
        }


        如上所示,代碼聲明了一個類Test,假設該類有一個十分耗時的成員函數:insert(),這個求和函數每次執行需要2000ms的時間。對于如此耗時的函數,我們在設計時都會想方法將其設計為線程函數,這樣調用者才不會阻塞。 
        于是我們為其加上多線程:

        #include <stdio.h>
        #include <stdlib.h>
        #include <iostream>
        #include <time.h>
        #include <unistd.h>
        #include <pthread.h>
        using namespace std;
        class Test
        {
            public:
                int sum=0;
                int cnt;
            public:
                int insert();
                void * insert_pth(void*);
                void lanch();
        };
        int Test::insert()
        {
            sleep(2);
            sum+=1;
        }
        void * Test::insert_pth(void*)
        {
            insert();
        }
        void Test::lanch()
        {
            pthread_t pth;
            pthread_create(&pth,NULL,insert_pth,NULL);
        }
        int main()
        {
            Test t;
            t.lanch();
            return 0;
        }

        以上代碼通過調用lanch()來創建多線程來執行insert_pth,insert_pth 再調用insert(). 
        但是 這樣的代碼在編譯時即會報錯。

        pthread.cpp: In member function ‘void Test::lanch()’:
        pthread.cpp:30:42: error: invalid use of non-static member function
          pthread_create(&pth,NULL,insert_pth,NULL);


        只需將insert_pth變化為static函數,同時將insert邏輯代碼轉移到insert_pth即可

        #include <stdio.h>
        #include <stdlib.h>
        #include <iostream>
        #include <time.h>
        #include <unistd.h>
        #include <pthread.h>
        using namespace std;
        class Test
        {
            public:
                int sum=0;
                int cnt;
            public:
                int insert();
            static  void * insert_pth(void*);
                void lanch();
        };
        int Test::insert()
        {
            sleep(2);
            sum+=1;
            printf("%d insert.....\n",sum);
        }
        void * Test::insert_pth(void* __this)
        {
            Test * _this =(Test *)__this;
            sleep(2);
            _this->sum+=1;
            printf("%d insert.....\n",_this->sum);
        }
        void Test::lanch()
        {
            pthread_t pth;
            pthread_create(&pth,NULL,insert_pth,(void*)this);
        }
        int main()
        {
            Test t;
            t.sum=0;
            t.lanch();
            sleep(5);
            return 0;
        }

        總結

        使用多線程處理耗時成員函數的步驟: 
        1. 聲明另外一個靜態函數:static void XXX_pth(void __this); 
        該函數與目標成員函數在函數名盡量保持一致 
        2. 將原成員函數的代碼拷貝至void * XXX_pth(void * __this); 
        在 XXX_pth()開始處將void * __this 轉化為 對象的指針 ObjectPoint _this; 
        將拷貝下來的所有成員變量加上_this-> 
        3. 編寫線程啟動代碼。 
        注意pthread_create()最后一個參數傳入this指針

        注意

        在 XXX_pth()函數內容不要調用類的其它成員函數,否則成員函數將無法獲取正確的指針而操作錯誤內存,從而導致segmantation fault.

        在C++的類中,普通成員函數不能作為pthread_create的線程函數,如果要作為pthread_create中的線程函數,必須是static !

                在C語言中,我們使用pthread_create創建線程,線程函數是一個全局函數,所以在C++中,創建線程時,也應該使用一個全局函數。static定義的類的成員函數就是一個全局函數。

         

        更多 參考  http://blog.csdn.net/ksn13/article/details/40538083 


        #include <pthread.h>
        #include <unistd.h>
        #include <stdio.h>
        #include <stdlib.h>
        
        class Thread
        {
            private:
                pthread_t pid;
            private:
                static void * start_thread(void *arg);// //靜態成員函數
            public: 
                int start();
                virtual void run() = 0; //基類中的虛函數要么實現,要么是純虛函數(絕對不允許聲明不實現,也不純虛)
        };
        
        int Thread::start()
        {
            if(pthread_create(&pid,NULL,start_thread,(void *)this) != 0) //′創建一個線程(必須是全局函數)
            {    
                return -1; 
            }    
            return 0;
        }
        
        void* Thread::start_thread(void *arg) //靜態成員函數只能訪問靜態變量或靜態函數,通過傳遞this指針進行調用
        {
            Thread *ptr = (Thread *)arg;
            ptr->run();  //線程的實體是run
        }
        
        
        
        class MyThread:public Thread
        {
            public: 
                void run();
        };
        void MyThread::run()
        {
            printf("hello world\n");
        }
        
        int main(int argc,char *argv[])
        {
            MyThread myThread;
            myThread.start();
            //test.run();
            sleep(1);
            return 0;
        }

        編譯運行:

        diego@ubuntu:~/myProg/pthreadCpp$ g++ main.cpp -lpthread
        diego@ubuntu:~/myProg/pthreadCpp$ ./a.out 
        hello world
        diego@ubuntu:~/myProg/pthreadCpp$


        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



        關鍵詞: C++

        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 纳雍县| 绥芬河市| 尉犁县| 怀远县| 巴彦淖尔市| 大足县| 内黄县| 枣强县| 德安县| 加查县| 云和县| 长乐市| 正阳县| 南雄市| 娄底市| 淅川县| 海安县| 休宁县| 锡林浩特市| 福建省| 沁源县| 台东县| 昌都县| 东阿县| 虹口区| 绿春县| 永定县| 开远市| 南康市| 萨迦县| 齐齐哈尔市| 四子王旗| 民丰县| 磐安县| 三台县| 鄂托克旗| 洪江市| 巫山县| 托里县| 南涧| 鄂温|