2017-04-01 111 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