我正在为我的项目(Linux,ICC,pthreads)优化一些检测,并希望对这种技术的一些反馈为线程分配一个唯一的索引,所以我可以使用它来索引到一个数组线程数据。
旧技术使用基于pthread id的std :: map,但是如果可能的话,我想避免锁定和地图查找(它会产生大量的开销)。
这是我的新技术:
static PerThreadInfo info[MAX_THREADS]; // shared, each index is per thread
// Allow each thread a unique sequential index, used for indexing into per
// thread data.
1:static size_t GetThreadIndex()
2:{
3: static size_t threadCount = 0;
4: __thread static size_t myThreadIndex = threadCount++;
5: return myThreadIndex;
6:}
稍后在代码中:
// add some info per thread, so it can be aggregated globally
info[ GetThreadIndex() ] = MyNewInfo();
所以:
1)如果在完全相同的时间创建两个线程,则第4行看起来可能是竞争条件。如果是这样 - 我怎么能避免这种情况(最好没有锁)?我无法看到原子增量在这里会有什么帮助。
2)是否有更好的方法以某种方式创建每线程索引?也许是通过某种方式在线程创建时预先生成TLS索引?
答案 0 :(得分:2)
1)原子增量实际上会有所帮助,因为可能的竞争是两个线程读取并为自己分配相同的ID,因此确保增量(读取数字,添加1,存储编号)以原子方式修复竞争条件。在英特尔,“lock; inc”可以解决这个问题,或者你的平台提供的任何东西(例如Windows的InterlockedIncrement())。
2)好吧,你实际上可以创建整个信息thread-local(“__thread static PerThreadInfo info;”),前提是你唯一的目标是能够轻松地以通用名称访问每个线程的数据。如果您确实希望它是一个全局可访问的数组,那么像使用TLS一样保存索引是一种非常简单有效的方法。你也可以预先计算索引,并在创建线程时将它们作为参数传递,正如Kromey在他的帖子中所说的那样。
答案 1 :(得分:1)
为什么如此厌恶使用锁?解决竞争条件正是他们为......设计的......
无论如何,您可以使用pthread_create()中的第4个参数将参数传递给线程的启动例程;通过这种方式,您可以使用主进程在启动线程时生成递增计数器,并在创建时将此计数器传递给每个线程,为每个线程提供唯一索引。
答案 2 :(得分:0)
我知道你标记了这个[pthreads],但你也提到了使用std :: map的“旧技术”。这让我相信你是用C ++编程的。在C ++ 11中你有std :: thread,你可以在线程创建时通过一个普通的函数参数将唯一索引(id)传递给你的线程。
下面是一个示例HelloWorld,它创建N个线程,为每个线程分配0到N-1的索引。每个线程只做“hi”并给它的索引:
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
inline void sub_print() {}
template <class A0, class ...Args>
void
sub_print(const A0& a0, const Args& ...args)
{
std::cout << a0;
sub_print(args...);
}
std::mutex&
cout_mut()
{
static std::mutex m;
return m;
}
template <class ...Args>
void
print(const Args& ...args)
{
std::lock_guard<std::mutex> _(cout_mut());
sub_print(args...);
}
void f(int id)
{
print("This is thread ", id, "\n");
}
int main()
{
const int N = 10;
std::vector<std::thread> threads;
for (int i = 0; i < N; ++i)
threads.push_back(std::thread(f, i));
for (auto i = threads.begin(), e = threads.end(); i != e; ++i)
i->join();
}
我的输出:
This is thread 0
This is thread 1
This is thread 4
This is thread 3
This is thread 5
This is thread 7
This is thread 6
This is thread 2
This is thread 9
This is thread 8