我使用的BlockingQueue代碼張貼in this question,但我意識到我需要使用堆棧而不是給定我的程序如何運行的隊列。我將它轉換爲使用堆棧並根據需要重命名類。爲了提高性能,我刪除了Push中的鎖定,因爲我的生產者代碼是單線程的。如何使Stack.Pop線程安全
我的問題是如何可以線程安全棧上的線程工作知道什麼時候它是空的。即使我添加了另一個線程安全包裝器,這個包圍着像Push和Pop這樣的底層集合的Count,我仍然遇到訪問Count和Pop的競爭條件不是原子的。
可能的解決方案,因爲我看到他們(這是首選和我失去了任何會更好地工作?):
- 消費者線程追趕()波普拋出InvalidOperationException異常。
- Pop()在_stack-> Count == 0時返回nullptr,但是C++ - CLI沒有默認的()運算符ala C#。
- Pop()返回一個布爾值並使用輸出參數返回彈出的元素。
這裏是我使用的是現在的代碼:
generic <typename T>
public ref class ThreadSafeStack
{
public:
ThreadSafeStack()
{
_stack = gcnew Collections::Generic::Stack<T>();
}
public:
void Push(T element)
{
_stack->Push(element);
}
T Pop(void)
{
System::Threading::Monitor::Enter(_stack);
try {
return _stack->Pop();
}
finally {
System::Threading::Monitor::Exit(_stack);
}
}
public:
property int Count {
int get(void)
{
System::Threading::Monitor::Enter(_stack);
try {
return _stack->Count;
}
finally {
System::Threading::Monitor::Exit(_stack);
}
}
}
private:
Collections::Generic::Stack<T> ^_stack;
};
「爲了提高性能,我刪除了Push中的鎖定,因爲我的生產者代碼是單線程的。」 這是什麼意思?你只有一個製片人?您的生產者代碼是否與消費者同時運行? – tony 2010-03-15 21:04:39
是的,我只有一個生產者,並且我的生產者代碼不會與消費者同時運行。它首先運行,然後使用生產者生成的ThreadSafeStack運行多個消費者。 – 2010-03-15 21:38:52