2016-01-22 88 views
0

我想打印數據隊列的元素的當前數目在每一秒在多線程的程序是這樣的:打印當前數

queue<int> products; 
void print(ostream& s) 
{ 
    cout << s.rdbuf(); 
    cout.flush(); 
    s.clear(); 
} 
void printQueue() 
{ 
    while(true) 
    { 
     this_thread::sleep_for(chrono::seconds(1)); 
     print(stringstream() << "Number of prouducts: " << products.size() << "\n"); 
    } 
} 

void producer(int i) 
{ //adds data into queue in thread safe manner 
} 
void consumer(int i) 
{/*removes data from queue in thread safe manner*/} 

int main() 
{ 
    vector<thread> thrds; 

    for(int i = 0; i < 5; ++i) 
     thrds.push_back(thread(producer, i)); 

    for(int i = 0; i < 4; ++i) 
     thrds.push_back(thread(consumer, i)); 

    thrds.push_back(thread(printQueue)); 

    for(auto& t : thrds) 
     t.join(); 
} 
return 0; 
} 

打印隊列 - 這是功能線程安全?

回答

2

有兩種資源被多個線程訪問:

  • std::cout
  • products

std::cout典型實現相對性能穩定的多個線程被訪問,但他們並不能保證該輸出不是例如交錯。不過,在形式上沒有同步,所以你的寫作不是線程安全的。

關於products,您的訪問有不被任何互斥被保護的,這也使得這些訪問非線程安全的。在一些地方你只能閱讀尺寸並不重要。並不是說這個讀取訪問可能會破壞任何內容,但結果(即,當您看到更改和看到的內容)仍未定義。

摘要:使用互斥鎖來保護共享資源。

0

身爲std::queue合同printQueue線程安全與否depeneds。對於他們公開方法的每個集裝箱特定線程的行爲就屬於下列主要類別之一:

  • 線程同步
  • 線程安全
  • 線程不安全的(可以產生一個種族)

第三個意思是說這個調用永遠不能用在不受保護的環境中 - 也就是說,在這個調用正在發生時,不能有任何其他方法調用容器的其他方法。 1和2之間的區別在於,對於第一個選項,您保證在另一個線程中修改後(在合理的延遲時間內)修改後讀取新值。線程安全不會給你這個保證,但仍然聲明調用這個方法不會讓你的程序暴露於數據競爭,並且你保證讀取舊值或新值,但是沒有未定義的行爲。

對於標準容器作爲std::queue,他們所有的常量方法是線程安全的,而非常量的方法是線程安全的。由於您將調用線程不安全推送,因此您需要使用外部同步來保護您的訪問。

+0

你能不能給一個指針,指示常量的訪問是線程安全的?我評論了一個收益(現在已刪除)的答案,其中提出了類似的聲明,並且確定「deque」的大小可能需要跳過幾個指針,所以任何兩者之間的變化都可能導致競爭。 –

+0

@UlrichEckhardt,我相信上面已經說清楚了。 deque的size()是線程安全的,也就是說,你可以同時從多個線程調用它。同時不安全的函數調用它是一個數據的比賽,而且我明確提出這樣:*意義,不可能有其他調用到容器的任何其他方法,而這個調用發生* – SergeyA

+0

因此,所有你需要做的安全地使用size()可以確保沒有其他線程同時調用不安全的方法。你有什麼關於如何實現這種魔法的建議嗎?如果沒有這種保護,尺寸方法的「線程安全性」並不值得。 –