2012-01-29 79 views
0

我需要有一個類,每個活動在其自己的線程中每5秒執行一次。它是一個Web服務,所以它需要指定一個端點。在對象運行期間,主線程可以更改端點。這是我的課程:進程間對象傳遞

class Worker 
{ 
    public: 
    void setEndpoint(const std::string& endpoint); 

    private: 
    void activity (void); 

    mutex endpoint_mutex; 
    volatile std::auto_ptr<std::string> newEndpoint; 

    WebServiceClient client; 
} 

是否需要將newEndpoint對象聲明爲volatile?我肯定會這樣做,如果閱讀是在一些循環(使編譯器不優化它),但在這裏我不知道。

在每次運行中,activity()函數都會檢查新端點(如果有新端點,則將其傳遞給客戶端並執行一些重新連接步驟)並執行其工作。

void Worker::activity(void) 
{ 
    endpoint_mutex.lock(); //don't consider exceptions 
    std::auto_ptr<std::string>& ep = const_cast<std::auto_ptr<string> >(newEndpoint); 
    if (NULL != ep.get()) 
    { 
     client.setEndpoint(*ep); 
     ep.reset(NULL); 
     endpoint_mutex.unlock(); 
     client.doReconnectionStuff(); 
     client.doReconnectionStuff2(); 
    } 
    else 
    { 
     endpoint_mutex.unlock(); 
    } 

    client.doSomeStuff(); 
    client.doAnotherStuff(); 
    ..... 
} 

我鎖定互斥的,這意味着所述newEndpoint對象不能再改變,所以我刪除揮發性類規範,以便能夠調用常量方法。

的對setEndpoint方法(從另一個線程調用):

void Worker::setEndpoint(const std::string& endpoint) 
{ 
    endpoint_mutex.lock(); //again - don't consider exceptions 
    std::auto_ptr<std::string>& ep = const_cast<std::auto_ptr<string> >(newEndpoint); 
    ep.reset(new std::string(endpoint); 
    endpoint_mutex.unlock(); 
} 

是這件事情的線程安全嗎?如果不是,問題是什麼?我是否需要newEndpoint對象是易變的?

回答

1

volatile在下列情況下,使用每MSDN:

volatile關鍵字是用於聲明一個 對象可以在程序中的東西,如 操作系統改性類型限定符,所述硬件或同時執行的線程。聲明爲volatile

對象在一定的優化 不使用,因爲它們的值可以在任何時候改變。即使先前的指令要求來自同一對象的值,系統始終會在要求的位置讀取易失性對象的當前值 , 。 另外,對象的值立即寫入賦值。

您的情況的問題是,您的NewEndPoint實際上多久改變一次?你在線程A中創建一個連接,然後你做一些工作。在發生這種情況時,沒有其他任何東西可以擺弄您的端點,因爲它被互斥鎖鎖定。所以,根據我的分析以及我在代碼中可以看到的內容,這個變量不一定會發生變化。

我看不到你的類的調用網站,所以我不知道你是否使用相同的類實例100次或更多,或者如果你正在創建新的對象。

當詢問是否應該是volatile時,需要進行這種分析。

而且,在你的線程安全,這些功能會發生什麼:

client.doReconnectionStuff(); 
client.doReconnectionStuff2(); 

使用任何共享狀態的從你的Worker類他們?他們是否正在共享和修改其他線程使用的其他狀態?如果是的話,你需要做適當的同步。

如果沒有,那麼你沒事。

線程化需要一些思考,你需要問自己這些問題。你需要看看所有的狀態,並想知道你是否在分享。如果你正在處理指針,那麼你需要懷疑誰擁有指針,以及你是否曾經意外地在線程中分享它,並據此採取行動。如果您將指針傳遞給在另一個線程中運行的函數,那麼您將共享該指針指向的對象。如果您在這個新線程中更改了它指向的內容,那麼您正在共享並需要同步。