同时循环同步

时间:2014-11-21 20:13:47

标签: c linux pthreads semaphore

我正在开发一个项目,其中包含用户定义的线程数目。我有一个在每个线程中运行的while循环,但我需要所有的线程在while循环结束时等待彼此。棘手的是,一些线程并非都通过循环以相同的次数结束。

void *entryFunc(void *param)
{
    int *i = (int *)param;
    int nextPrime;
    int p = latestPrime;
    while(latestPrime < testLim)
    {

        sem_wait(&sem);
        nextPrime = findNextPrime(latestPrime);
        if(nextPrime != -1)
        {
            latestPrime = nextPrime;
            p = latestPrime;
        }
        else
        {
            sem_post(&sem);
            break;
        }

        sem_post(&sem);
        if(p < 46341)
        {
            incrementNotPrimes(p);
        }
/*
        sem_wait(&sem2);
        doneCount++;
        sem_post(&sem2);

        while(go != 1);

        sem_wait(&sem2);
        doneCount--;
        //sem_post(&sem3);
        sem_post(&sem2);
*/
    }
    return NULL;
}

代码块被注释掉的地方是我上次尝试解决这个问题的一部分。这就是所有功能都需要彼此等待的地方。我有一种感觉,我错过了一些简单的东西。

2 个答案:

答案 0 :(得分:1)

如果您的问题是在每个线程上,while循环具有不同的迭代次数,并且一些线程在退出循环后永远不会到达同步点,则可以使用屏障。请查看 here 以获取示例。

但是,在退出每个线程后,您需要减少屏障处的线程数。等待屏障将在计数线程数达到该点后结束。

因此,每次线程完成时都需要更新barrier对象。并确保你原子地这样做。

答案 1 :(得分:0)

正如我在评论中提到的,在这种情况下你应该使用障碍而不是信号量,因为它应该更容易实现(障碍的设计正是为了解决这个问题)。但是,您仍然可以使用信号量和一点算术 算术:你的目标是让所有线程执行相同的代码路径,但不知何故,完成其任务的最后一个线程应该唤醒所有其他线程。实现这一目标的一种方法是在函数末尾 一个原子计数器,每个线程将减少,如果计数器达到0,则线程只调用sem_post {{ 1}}根据需要释放所有等待的线程,而不是像其他线程一样发出sem_wait

第二种方法,这次只使用一个信号量,也是可能的。由于我们无法区分其他线程的最后一个线程,所有线程必须对信号量执行相同的操作,即尝试释放所有人,但也等待最后一个。因此,我们的想法是将信号量初始化为(1-n)*(n+1),这样每个n-1第一个线程都会在通过n+1调用sem_post来唤醒他们的朋友时失败,但仍然努力获得信号量0。然后最后一个线程也会这样做,将信号量值推送到n+1,从而释放锁定的线程,并留出空间让它也执行sem_wait并立即释放。

void *entryFunc(void *param)
{
  int *i = (int *)param;
  int nextPrime;
  int p = latestPrime, j;
  while(latestPrime < testLim){
    nextPrime = findNextPrime(latestPrime);
    if(nextPrime != -1)
    {
        latestPrime = nextPrime;
        p = latestPrime;
    }
    if(p < 46341)
    {
        incrementNotPrimes(p);
    }
  }
  for (j=0;j<=THREAD_COUNT;j++)
    sem_post(&sem);
  sem_wait(&sem);
  return NULL;
}

这种方法的问题在于它没有处理如何在两次使用之间重置信号量(如果你的程序需要重复这种机制,它将需要重置信号量值,因为它将结束在成功执行此代码后,为1