[英]QNX c++ thread question
我有一個關於此代碼的問題,我想在QNX上運行:
class ConcreteThread : public Thread
{
public:
ConcreteThread(int test)
{
testNumber = test;
}
void *start_routine()
{
for(int i = 0; i < 10; i++)
{
sleep(1);
cout << testNumber << endl;
}
}
private:
int testNumber;
};
class Thread
{
public:
Thread(){};
int Create()
{
pthread_t m_id;
return pthread_create(&m_id, NULL, &(this->start_routine_trampoline), this);
}
protected:
virtual void *start_routine() = 0;
private:
static void *start_routine_trampoline(void *p)
{
Thread *pThis = (Thread *)p;
return pThis->start_routine();
}
};
現在,當我在* start_routine中沒有睡眠的情況下運行此代碼時,它將簡單地打印數字10次,然后繼續下一行代碼(順序而不是並行)。 但是,當我在代碼中使用睡眠時,它根本不打印任何數字,只是繼續下一行代碼。 為什么不睡覺工作,我怎樣才能創建這樣的線程,而不是運行順序?
注1:如果您只有1個處理器,則無論您創建多少個線程,代碼都只能按順序執行。 每個線程在換出下一個線程之前都會獲得一段處理器時間。
注意2:如果主線程退出pthreads將在它們有機會執行之前終止所有子線程。
現在回答你的問題:
沒有睡覺。 線程一旦啟動就有足夠的時間在單個切片中給出完全執行循環10次。
隨着睡眠:你的工作線程將睡一整秒。 所以你的主線程有時間做很多工作。 如果主線程在此時退出,則工作人員將被殺死。
我會做出以下更改:
// Remove the Create() method
// Put thread creation in the constructor.
// Make the thread variable part of the object
pthread_t m_id;
Thread()
{
if (pthread_create(&m_id, NULL, &(this->start_routine_trampoline), this) != 0)
{
throw std::runtime_error("Thread was not created");
}
}
// Make sure the destructor waits for the thread to exit.
~Thread()
{
pthread_join(m_id);
}
如果你去看看增強線程庫。 你會發現像這樣的所有小錯誤已經得到了照顧; 從而使線程更易於使用。
另請注意。 使用靜態可能有效,但它不可移植。 這是因為pthread是一個C庫,因此期望一個帶有C ABI的函數指針。 您只是在這里為您的平台幸運。 您需要將此定義為函數並使用extern“C”聲明ABI
// This needs to be a standard function with C Interface.
extern "C" void *start_routine_trampoline(void *p)
{
}
嘗試使pthread_t id成為類成員而不是函數局部變量。 這樣調用者可以pthread_join它。
不這樣做在技術上是資源泄漏(除非線程特別不可連接)。 加入將避免Martin York描述的問題。
來自man pthread_join:
連接的線程必須處於可連接狀態:它不能使用pthread_detach(3)或PTHREAD_CREATE_DETACHED屬性分離到pthread_create(3)。
當可連接線程終止時,其內存資源(線程描述符和堆棧)不會被釋放,直到另一個線程對其執行pthread_join。 因此,必須為創建的每個可連接線程調用pthread_join一次,以避免內存泄漏。
關於這里的切線...關於馬丁約克的帖子:
另請注意。 使用靜態可能有效,但它不可移植。 這是因為pthread是一個C庫,因此期望一個帶有C ABI的函數指針。 您只是在這里為您的平台幸運。 您需要將此定義為函數並使用extern“C”聲明ABI
我不太確定......
(1)C ++被設計為盡可能與C兼容。 有一些差異......但我的印象是extern“C”主要用於規避實現C ++函數重載所需的名稱修改。
(2)看起來,一旦你有了函數指針,調用約定(在堆棧上被推入以進行函數調用)在C&C ++之間必須是相同的。 否則,函數指針將如何工作?
例如:
C代碼:
void bar( int i ) { printf( "bar %d\n", i ); }
C ++代碼:
class Foo
{
public:
static void foo( int i ) { cout << "foo " << i << endl; }
};
extern "C" { void bar(int); }
int main()
{
void (*p)(int);
p = & Foo::foo;
(*p)(1);
p = & bar;
(*p)(2);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.