概念线程问题

时间:2012-10-02 04:46:05

标签: c multithreading pthreads

我在某些线程中生成从1到N的哈希值(MD5)。根据哈希的第一个字母,生成它的数字存储在一个数组中。例如,数字1导致c4ca4238a0b923820dcc509a6f75849b和c81e728d9d4c2f636f067f89cc14862c中的数字2,因此它们存储在以“c”开头的特定散列数组中。

问题是我需要生成从低到高排序的它们。在序列完成后对它们进行排序是非常昂贵的,N可以大到2 ^ 40。当我使用线程时,排序永远不会自然发生。例如。一个线程可以生成数字12的散列(c20ad4d76fe97759aa27a0c99bff6710)并将其存储在“c”数组中,然后生成数字8的散列(c9f0f895fb98ab9159f51fd0297e236d)并将其存储在“c”数组中的数字12之后。

我不能简单地验证数组上的最后一个数字,因为只要线程运行它们就可以相距很远。

这个线程问题有什么解决方案吗?在完成所有线程之后,任何比排序数组更快的解决方案都会很棒。

我在C中实现了这个。

谢谢!

2 个答案:

答案 0 :(得分:2)

不是每个前缀都有一个数组(例如“c”),每个前缀的每个线程都有一个数组。每个线程只插入到自己的数组中,因此它总是以递增的顺序插入数字,并且各个线程数组将保持排序。

然后,您可以在进程结束时快速(O(N))合并数组,因为各个数组都将被排序。这也将加快创建过程,因为您不需要在阵列周围进行任何锁定。

答案 1 :(得分:0)

既然你提到了pthreads我会假设你正在使用gcc(这不一定是这种情况,但可能就是这种情况)。您可以使用__sync_fetch_and_add获取数组末尾的值,并在一个原子操作中为其添加一个值。它将类似于以下内容:

insertAt = __sync_fetch_and_add(&size[hash], 1);
arrayOfInts[insertAt] = val;

您遇到的唯一问题是您是否需要调整阵列大小(不确定您是否事先知道阵列大小)。为此,您将需要一个锁(每个阵列最有效一个锁),您在重新分配数组时会独占锁定,而在插入时则是非独占的。特别是这可以通过以下函数完成(假设程序员不释放解锁的锁定):

// Flag 2 indicates exclusive lock
void lockExclusive(int* lock)
{
    while(!__sync_bool_compare_and_swap(lock, 0, 2));
}

void releaseExclusive(int* lock)
{
    *lock = 0;
}

// Flag 8 indicates locking
// Flag 1 indicates non-exclusive lock
void lockNonExclusive(int* lock, int* nonExclusiveCount)
{
    while((__sync_fetch_and_or(lock, 9) & 6) != 0);
    __sync_add_and_fetch(nonExclusiveCount, 1);
    __sync_and_and_fetch(lock, ~8);
}

// Flag 4 indicates unlocking
void releaseNonExclusive(int* lock, int* nonExclusiveCount)
{
    while((__sync_fetch_and_or(lock, 4) & 8) != 0);
    if(__sync_sub_and_fetch(nonExclusiveCount) == 0);
        __sync_and_and_fetch(lock, ~1);
    __sync_and_and_fetch(lock, 4);
}