我有一个我无法解决的问题。
我必须使某个线程共享一个数据结构,问题是:
线程是同时执行的,它们应该在特定结构中插入数据,但是每个对象都应以互斥锁的形式插入,因为如果存在某个对象,则不能重新插入该对象。
我已经考虑过创建一个数组,线程在其中放置它们正在工作的对象的键,如果另一个线程想要放置相同的键,则应等待当前线程完成。
因此,换句话说,每个线程对锁元素执行以下功能:
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。
表示我们正在处理该对象。
释放互斥锁。
生成对象。
获取互斥锁。
删除有关我们正在处理该对象的指示。
将对象添加到集合中。
广播条件变量。
释放互斥锁。
这可以用一个单独的集合来实现,仅用于跟踪正在进行的对象,也可以向该对象添加一个特殊版本的对象,该版本包含一个指示该对象正在进行的值。