2011-10-14 47 views
4

我做了下面的示例程序與提升線程玩:boost :: scoped_lock不能使用本地靜態變量?

#pragma once 
#include "boost\thread\mutex.hpp" 
#include <iostream> 

class ThreadWorker 
{ 
public: 
    ThreadWorker() {} 
    virtual ~ThreadWorker() {} 

    static void FirstCount(int threadId) 
    { 
     boost::mutex::scoped_lock(mutex_); 
     static int i = 0; 

     for(i = 1; i <= 30; i++) 
     { 
      std::cout << i << ": Hi from thread: " << threadId << std::endl; 
     } 

    } 

private: 
    boost::mutex mutex_; 
}; 

主類:

// ThreadTest.cpp 
#include "stdafx.h" 
#include "boost\thread\thread.hpp" 
#include "ThreadWorker.h" 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    boost::thread thread1(&ThreadWorker::FirstCount, 1); 
    boost::thread thread2(&ThreadWorker::FirstCount, 2); 
    boost::thread thread3(&ThreadWorker::FirstCount, 3); 

    thread1.join(); 
    thread2.join(); 
    thread3.join(); 

    std::string input; 
    std::cout << "Press <enter> to finish...\n"; 
    std::getline(std::cin, input); 
    return 0; 
} 

當我運行此我得到以下輸出:

1: Hi from thread: 1 
1: Hi from thread: 3 
2: Hi from thread: 3 
... 

它看起來像線程1先到達那裏然後線程3.是不是scoped_lock應該阻止其他線程輸入該代碼段?運行FirstCount()的第一個線程不應該完成嗎?

UPDATE

有一件事我認爲是錯我的代碼是這一行:

boost::mutex::scoped_lock(mutex_); 

我想應該是這樣的:

boost::mutex::scoped_lock xyz(mutex_); 

一旦我做到這一點,它確實使關於mutex_的投訴不是靜態的。爲什麼它首先在我不確定的地方工作。將互斥鎖變爲靜態會給我一個鏈接錯誤:

1>ThreadWorker.obj : error LNK2001: unresolved external symbol "private: static class boost::mutex ThreadWorker::mutex_" ([email protected]@@[email protected]@@A) 1>c:\something\ThreadTest\Debug\ThreadTest.exe : fatal error LNK1120: 1 unresolved externals

仍然在玩它。

+2

該代碼不能編譯。在實際代碼中,'mutex_'是類中的一個靜態成員嗎​​? –

+2

'static int i'本質上是一個共享的全局變量,它不受保護(它受不同的互斥鎖保護......) – sehe

+0

它在Visual Studio 2010 C++中爲我編譯。我已經嘗試使mutex_既是靜態的也是非靜態的。無論哪種方式代碼編譯我和任何方式的結果是相同的。 – User

回答

6

你有兩個錯誤:

首先,由於已經注意到,mutex_應該是靜態也:

private: 
    static boost::mutex mutex_; 

當然,並宣佈它的地方(在.cpp文件最好!):

boost::mutex ThreadWorker::mutex_{}; 

現在,爲什麼編譯器不會抱怨?嗯,因爲你其實並不建立一個範圍的鎖用爭論mutex_這裏:

boost::mutex::scoped_lock(mutex_); 

其實這不叫你想要的構造,而是創建一個(本地)對象mutex_scoped_lock類型和構造由默認的構造函數。因此,沒有編譯器問題。你應該將其更改爲類似如下:

boost::mutex::scoped_lock l{mutex_}; 

現在,編譯器應該開始抱怨mutex_

+0

這是一個錯字?:'boost :: mutex :: scoped_lock l {mutex _};'爲什麼使用大括號?另外爲什麼在這裏括號? 'boost :: mutex ThreadWorker :: mutex _ {};'thx – User

+1

不是錯字,它是C++ 11改進的構造函數語法,可以防止一些常見問題。但我不知道Visual Studio是否支持它。 – KillianDS

+0

有趣我只是試過:'int(j);'它的工作原理是聲明一個整數j。我不知道那件事。有點可怕的'boost :: mutex :: scoped_lock(mutex _);'只是因爲它會默默接受它。 – User

3

你有三個獨立的對象,他們都不能看到對方的互斥體,因爲該成員是在每個對象內創建的。

也許你的意思是讓mutex_靜態?

編輯:如果我讓互斥體靜態並從我的變量中移除靜態,那麼它似乎工作,因爲我猜你的意思。似乎是這樣的事情發生:每個線程立即進入循環,並且由於互斥體不是靜態的而彼此鎖定。當他們將所有輸出輸出到控制檯(我不記得是否在寫入cout時是否存在相互排斥)並且我增加了他們都看到靜態我爲30並退出。

編輯2:不,仍然不正確,因爲在某些運行中仍然存在穿插值。

編輯3:它編譯的原因是你的scoped_lock是一個臨時的,似乎把編譯器的事實,mutex_應該是靜態的。請嘗試使用以下代碼:

#include <iostream> 
#include "boost\thread\mutex.hpp" 
#include "boost\thread\thread.hpp" 

class ThreadWorker 
{ 
public: 
    ThreadWorker() {} 
    virtual ~ThreadWorker() {} 

    static void FirstCount(int threadId) 
    { 
     // Created object f here rather than temprary 
     boost::mutex::scoped_lock f(mutex_); 
     int i = 0; // Not static 

     for(i = 1; i <= 30; i++) 
     { 
      std::cout << i << ": Hi from thread: " << threadId << std::endl; 
     } 

    } 

private: 
    static boost::mutex mutex_; // Static 
}; 

// Storage for static 
boost::mutex ThreadWorker::mutex_; 

int main(int argc, char* argv[]) 
{ 
    boost::thread thread1(&ThreadWorker::FirstCount, 1); 
    boost::thread thread2(&ThreadWorker::FirstCount, 2); 
    boost::thread thread3(&ThreadWorker::FirstCount, 3); 

    thread1.join(); 
    thread2.join(); 
    thread3.join(); 

    std::string input; 
    std::cout << "Press <enter> to finish...\n"; 
    std::getline(std::cin, input); 
    return 0; 
} 
+0

想到了同樣的事情,我試着讓mutex_靜態,但結果是一樣的。 – User

+0

@用戶:認爲我這次解決了它:) – tinman

+1

它傳遞的原因並不是因爲編譯器優化臨時(如果它會這樣做,許多RAII代碼將失敗)。它實際上並不構建您期望它構建的臨時。 – KillianDS

0

此代碼是否也使用相同的編譯器進行編譯?

你能看到這個代碼的問題嗎?嘗試發現問題而不編譯它。

 
class C { 
public: 
    static int f() { 
     return i; 
    } 

    int i; 
}; 

int main() { 
    return C::f(); 
} 

更新: 我剛剛閱讀您的更新。

 
class C { 
public: 
    static int f() { 
     return i; 
    } 

    static int i; 
}; 

int C::i = whatever; 

int main() { 
    return C::f(); 
} 
0

我的代碼更改爲:

ThreadWorker.h:

#pragma once 
#include "boost\thread\mutex.hpp" 
#include <iostream> 

class ThreadWorker 
{ 
public: 
    ThreadWorker(); 
    virtual ~ThreadWorker(); 

    static void FirstCount(int threadId); 

private: 
    static boost::mutex mutex_; 
}; 

ThreadWorker.cpp:

#include "stdafx.h" 
#include "ThreadWorker.h" 

boost::mutex ThreadWorker::mutex_; 

ThreadWorker::ThreadWorker() 
{ 
} 

ThreadWorker::~ThreadWorker() 
{ 
} 

void ThreadWorker::FirstCount(int threadId) 
{ 
    boost::mutex::scoped_lock xyz(mutex_); 
    static int i = 0; 

    for(i = 1; i <= 30; i++) 
    { 
     std::cout << i << ": Hi from thread: " << threadId << std::endl; 
    } 

} 

ThreadTest.cpp:

// ThreadTest.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#include "boost\thread\thread.hpp" 
#include "ThreadWorker.h" 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    boost::thread thread1(&ThreadWorker::FirstCount, 1); 
    boost::thread thread2(&ThreadWorker::FirstCount, 2); 
    boost::thread thread3(&ThreadWorker::FirstCount, 3); 

    thread1.join(); 
    thread2.join(); 
    thread3.join(); 

    std::string input; 
    std::cout << "Press <enter> to finish...\n"; 
    std::getline(std::cin, input); 
    return 0; 
} 

我所做的更改爲1分離的頭部和CPP文件(我原本只是這樣做是爲了讓我的文章更緊湊)2.給予的scoped_lock變量標識符和3 。使互斥體靜態化。

現在按預期工作,按順序從每個線程打印30行。還有什麼讓我感到困惑的是爲什麼之前編譯的代碼(因爲錫曼還能夠編譯我的原始代碼)。

+0

您保留了'static int'和'ThreadWorker'類。爲什麼? – curiousguy

+0

@curiousguy:靜態int是故意的。我想測試鎖定共享資源。我不確定你對ThreadWorker類的含義。 – User

+0

這個班有什麼意義? – curiousguy