第 4章 線程管理:ACE 的同步和線程管理機制

第 4章 線程管理:ACE 的同步和線程管理機制

標籤ACE  線程  機制  管理  2008-12-10 09:16
出自:《ACE程序員指南》
     ACE 擁有許多不同的用於創建和管理多線程程序的類。在這一章裏,我們將查看 ACE 中的一些線程管理機制。在一開始,我們將查看那些簡單的線程包裝類,它們的管理功能很少。但是,隨着內容的進展,我們將查看 ACE_Thread_Manager 中的更爲強大的管理機制。ACE 還擁有一組非常全面的處理線程同步的類。這些類也將在本章講述。
 
4.1  創建和取消線程
    在不同的平臺上,有着若干不同的用於線程管理的接口。其中包括 POSIX pthreads 接口、Solaris 線程、Win32 線程等等。這些接口提供了相同或是相似的功能,但是它們的 API 的差別卻極爲懸殊。這就導致了困難、麻煩和易錯的編程,因爲應用程序員必須熟悉不同平臺上的若干接口。而且,這樣寫下的程序,是不可移植和不靈活的。
     ACE_Thread提供了對 OS的線程調用的簡單包裝,這些調用處理線程創建、掛起、取消和刪除等問題。它提供給應用程序員一個簡單易用的接口,可以在不同的線程 API 間移植。ACE_Thread 是非常“瘦”的包裝,有着很少的開銷。其大多數方法都是內聯的,因而等價於對底層 OS專有線程接口的直接調用。ACE_Thread中的所有方法都是靜態的,而且該類一般不進行實例化。

下面的例子演示怎樣使用 ACE_Thread 包裝類創建、生成和聯接(join)線程。
 
#include "ace/Thread.h"
#include "ace/Synch.h"
static int number=0;
static int seed = 0;
static void* worker(void *arg)
{
    ACE_UNUSED_ARG(arg);
    ACE_DEBUG((LM_DEBUG,"Thread (%t) Created to do some work"));
    ::number++;
    ACE_DEBUG((LM_DEBUG," and number is %d/n",::number));
//Let the other guy go while I fall asleep for a random period
//of time
    ACE_OS::sleep(ACE_OS::rand()%2);
//Exiting now
    ACE_DEBUG((LM_DEBUG,
               "/t/t Thread (%t) Done! /t The number is now: %d/n",number));
    return 0;
}
int main(int argc, char *argv[])
{
    if (argc<2)
    {
        ACE_DEBUG((LM_DEBUG,"Usage: %s <number of threads>/n", argv[0]));
        ACE_OS::exit(1);
    }
    ACE_OS::srand(::seed);
//setup the random number generator
    int n_threads= ACE_OS::atoi(argv[1]);
//number of threads to spawn
    ACE_thread_t *threadID = new ACE_thread_t[n_threads+1];
    ACE_hthread_t *threadHandles = new ACE_hthread_t[n_threads+1];
    if (ACE_Thread::spawn_n(threadID,    //id!ˉs for each of the thread
                            n_threads,       //number of threads to spawn
                            (ACE_THR_FUNC)worker,      //entry point for new thread
                            0,         //args to worker
                            THR_JOINABLE | THR_NEW_LWP,   //flags
                            ACE_DEFAULT_THREAD_PRIORITY,
                            0, 0, threadHandles)==-1)
        ACE_DEBUG((LM_DEBUG,"Error in spawning thread/n"));
//spawn n_threads
    for (int i=0; i<n_threads; i++)
        ACE_Thread::join(threadHandles[i]);
//Wait for all the threads to exit before you let the main fall throug
//and have the process exit.
    return 0;
}

 
    在這個簡單的例子中,創建了 n_thread 個工作者線程。每個線程都執行程序中定義的 worker()函數。線程是通過使用 ACE_Thread::spawn_n()調用創建的。要作爲線程的執行啓動點調用的函數的指針(在此例中爲 worker()函數)被作爲參數傳入該調用中。要注意的重點是 ACE_Thread::spawn_n()要求所有的線程啓動函數(方法)必須是靜態的或全局的(就如同直接使用 OS線程 API 時所要求的一樣)。

    一旦工作者函數啓動,它將全局變量 number 的值加 1,報告它的當前值,然後進入休眠狀態,以把處理器讓給其他線程。sleep()休眠一段隨機長度的時間。在線程醒來後,它將 number 的當前值通知給用戶,然後退出 worker()函數。
     一旦線程從它的啓動函數返回,它在線程庫上隱含地發出線程 exit()調用並退出。這樣一旦“掉出”worker()函數,工作者線程也就退出了。負責創建工作者線程的主線程,在退出之前“等待”所有其他的線程完成它們的執行並退出。當主線程退出時(通過退出 main()函數),整個進程也將被銷燬。這之所以會發生是因爲每當線程退出 main()函數時,都會隱含地調用 exit(3c)函數。因此,如果主線程沒有被強制等待其他線程結束,當它死掉時,進程將會被自動銷燬,並在它的所有工作者線程完成工作之前銷燬它們!
       上面所說的等待是通過使用 ACE_Thread::join()調用來完成的。該方法的參數是你想要主線程與之聯
接的線程的句柄(ACE_hthread_t)。
      在此例中有若干事實值得注意。首先,在該類中沒有可供我們調用的管理功能,用以在內部記住應用所派生的線程的 ID。這使得我們難以聯接(join())、殺死(kill())或是一般性地管理我們派生的線程。在本章後面講述的 ACE_Thread_Manager 緩解了這些問題,一般說來,應該使用 ACE_Thread_Manager而不是線程包裝 API。
        其次,在程序中沒有使用同步原語來保護全局數據。在此例中,它們並不是必須的,因爲所有的線
程都只對全局變量執行一次加操作。但是在實際應用中,爲了保護所有共享互斥數據(全局或靜態變量),比如說全局的 number變量,“鎖”將會是必需的。
 
2008.12.10 haha123_0 Code::Blocks 8.02 ACE 5.6.7編譯通過:)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章