我有一个我无法解决的问题。
我必须使某个线程共享一个数据结构,问题是:
线程是同时执行的,它们应该在特定结构中插入数据,但是每个对象都应以互斥锁的形式插入,因为如果存在某个对象,则不能重新插入该对象。
我已经考虑过创建一个数组,线程在其中放置它们正在工作的对象的键,如果另一个线程想要放置相同的键,则应等待当前线程完成。
因此,换句话说,每个线程对锁元素执行以下功能:

void lock_element(key_t key){
  pthread_mutex_lock(&mtx_array);

  while(array_busy==1){
    pthread_cond_wait(&var_array,&mtx_array);
  }
  array_busy=1;
  if((search_insert((int)key))==-1){
        // the element is present in array and i can't insert,
        //  and i must wait for the array to be freed.
        // (i think that the problem is here)
  }
  array_busy=0;
  pthread_cond_signal(&var_array);
  pthread_mutex_unlock(&mtx_array);
}


在完成对象之后,我可以使用Follow函数释放arry中的键:

void unlock_element(key_t key){

  pthread_mutex_lock(&mtx_array);

  while(array_busy==1){
    pthread_cond_wait(&var_array,&mtx_array);
  }

  array_busy=1;
  zeroed((int)key);
  array_busy=0;
  pthread_cond_signal(&var_array);
  pthread_mutex_unlock(&mtx_array);
}


以这种方式,结果在每次执行中都会发生变化(例如:第一次是程序插入300对象,第二次是插入100对象)。

谢谢您的帮助!

更新:

@DavidSchwartz @Asthor我将代码修改如下:

  void lock_element(key_t key){
   pthread_mutex_lock(&mtx_array);
   while((search_insert((int)key))==-1){
         //wait
         pthread_cond_wait(&var_array,&mtx_array);
     }
   pthread_mutex_unlock(&mtx_array);
 }


和...

 void unlock_element(key_t  key){
 pthread_mutex_lock(&mtx_array);

 zeroed((int)key);
 pthread_cond_signal(&var_array);
 pthread_mutex_unlock(&mtx_array);
  }


但不起作用。它的行为与以前相同。

我还注意到函数search_insert(key)的奇怪行为;

  int search_insert(int key){
   int k=0;
   int found=0;
   int fre=-1;
   while(k<7 && found==0){
     if(array[k]==key){
         found=1;
     } else if(array[k]==-1) fre=k;
     k++;
   }
   if (found==1) {
     return -1; //we can't put the key in the array

   }else {
      if(fre==-1) exit(EXIT_FAILURE);
      array[fre]=key;
      return 0;
    }

  }


永远不会进去

  if(found == 1)

最佳答案

您有两种选择。

最简单的选择就是在整个操作过程中保持互斥量。除非您有充分的证据表明需要更大的并发性,否则您绝对应该选择此选项。

通常,可能只允许多个线程来完成工作。此模式如下所示:


获取互斥锁。
检查对象是否在集合中。如果是这样,请使用集合中的对象。
否则,释放互斥锁。
产生物件
再次获取互斥锁。
检查对象是否在集合中。如果没有,请添加它并使用您生成的对象。
否则,请丢弃生成的对象,然后使用集合中的对象。


这可能导致两个线程执行相同的工作。这在您的用例中可能是不可接受的,因为它是不可能的(某些工作只能完成一次),或者因为并发的收益不值得重复工作的代价。

如果没有其他效果,则可以采用更复杂的解决方案:


获取互斥锁。
检查对象是否在集合中。如果是这样,请使用集合中的对象。
检查对象上是否还有其他线程在工作。如果是这样,请阻止条件变量并转到步骤2。
表示我们正在处理该对象。
释放互斥锁。
生成对象。
获取互斥锁。
删除有关我们正在处理该对象的指示。
将对象添加到集合中。
广播条件变量。
释放互斥锁。


这可以用一个单独的集合来实现,仅用于跟踪正在进行的对象,也可以向该对象添加一个特殊版本的对象,该版本包含一个指示该对象正在进行的值。

09-11 19:27
查看更多