2017-04-01 108 views
0

據我所知,在lambda內使用靜態存儲是合法的。從本質上講,它計算進入封閉的條目數量:Lambda表達式,併發和靜態變量

#include <vector> 
#include <iostream> 
#include <algorithm> 
#include <iterator> 


typedef std::pair<int,int> mypair; 

std::ostream &operator<< (std::ostream &os, mypair const &data) { 
    return os << "(" << data.first << ": " << data.second << ") "; 
} 

int main() 
{ 
    int n; 
    std::vector<mypair> v; 
    std::cin >> n; 
    v.reserve(n); 

    std::for_each(std::begin(v), std::end(v), [](mypair& x) { 
     static int i = 0; 
     std::cin >> x.second; 
     x.first = i++; 
    }); 

    std::for_each(std::begin(v), std::end(v), [](mypair& x) { 
     std::cout << x; 
    }); 

    return 0; 
} 

假設我有一個容器'工作者'的線程。

std::vector<std::thread> workers; 
for (int i = 0; i < 5; i++) { 
    workers.push_back(std::thread([]() 
    { 
     std::cout << "thread #" << "start\n"; 
     doLengthyOperation(); 
     std::cout << "thread #" << "finish\n"; 
    })); 
} 

doLengthyOperation()中的代碼被包含和自給自足的操作,類似於一個新的進程創建。

提供我加入他們使用for_each和存儲的變量問題必須計數活動任務,而不僅僅是條目數,這種計數器有什麼可能的實現,如果我想避免依賴於全局變量以避免其他人搞亂它,並允許自動支持單獨的「線程風格」。

std::for_each(workers.begin(), workers.end(), [](std::thread &t) 
    { 
     t.join(); 
    }); 

周邊範圍將完成線程開始後很快死亡,可能重複,增加新線程的容器是可能的,而且必須是全局變量,這是我想避免的。更多的,整個操作是一個模板

回答

1

處理此問題的最佳方法是捕獲std::atomic<int>的實例,它提供了一個線程安全計數器。根據lambdas的生命週期和周圍範圍,您可能希望通過引用或共享指針進行捕獲。

爲了把你的例子:

std::vector<std::thread> workers; 
auto counter = std::make_shared<std::atomic<int>>(0); 
for (int i = 0; i < 5; i++) { 
    workers.push_back(std::thread([counter]() 
    { 
     std::cout << "thread #" << "start\n"; 
     (*counter)++; 
     doLengthyOperation(); 

     (*counter)--; 
     std::cout << "thread #" << "finish\n"; 
    })); 
} 
+0

周邊範圍將完成線程開始後很快死亡,可能重複,增加新線程的容器,必須是全球性的變量,這是我要廢寢忘食。更多的是,整個操作是一個模板。在範圍消失後提供計數器嗎? – Swift

+1

@Swift計數器必須與工作容器具有相同的範圍,如果需要全局計數器也需要。如果你有更多有關工作容器的細節,我可能會添加更多細節。 – user1937198

+0

啊哈,明白了。所以我可能仍然需要創建一個模板類來容納每種風味的容器和一個櫃檯。什麼阻止我在lambda中將計數器聲明爲靜態? – Swift