实现简单计数器所需的信号量或互斥量?

问题描述 投票:0回答:1

我尝试实现计算积分的程序。并且为了加速计算,一个创建多个进程,另一个使用多个线程。在我的程序中,每个进程都在共享内存中添加一个double值,每个线程通过指针添加一个double值。

这是我的问题。添加操作显然从内存加载值,为其添加值,并将结果存储到内存中。所以看起来我的代码很容易出现生产者 - 消费者问题,因为许多进程/线程访问相同的内存区域。但是,我找不到有人使用信号量或互斥量来实现简单累加器的情况。

// creating processes
while (whatever)
{
    pid = fork();
    if (pid == 0)
    {
        res = integralproc(clist, m, tmpcnt, tmpleft, tmpright);
        *(createshm(shm_key)) += res;
        exit(1);
    }
}
// creating or retrieving shared memory
long double* createshm(int key)
{
    int shm_id = -1;
    void* shm_ptr = (void*)-1;
    while (shm_id == -1)
    {
        shm_id = shmget((key_t)key, sizeof(long double), IPC_CREAT | 0777);
    }
    while (shm_ptr == (void*)-1)
    {
        shm_ptr = shmat(shm_id, (void*)0, 0);
    }
    return (long double*)shm_ptr;
}

// creating threads
while (whatever)
{
    threadres = pthread_create(&(targs[i]->thread_handle), NULL, integral_thread, (void*)targs[i]);
}
// thread function. targ->resptr is pointer that we add the result to.
void *integral_thread(void *arg)
{
    threadarg *targ = (threadarg*)arg;
    long double res = integralproc(targ->clist, targ->m, targ->n, targ->left, targ->right);
    *(targ->resptr) += res;
    //printf("thread %ld calculated %Lf\n", targ->i, res);
    pthread_exit(NULL);
}

所以我以这种方式实现它,到目前为止,无论我制作了多少进程/线程,结果都好像从未发生过。我担心我的代码可能仍然有潜在的危险,几乎不在我看来。这些代码真的可以安全地解决这些问题吗?或者我是否会忽视某些内容并且应该修改代码?

c pthreads fork shared-memory
1个回答
1
投票

如果你的线程都在竞相更新同一个对象(即每个线程的targ->resptr指向同一个东西),那么是 - 你确实有一个数据竞争,你可以看到不正确的结果(可能,“丢失更新”,其中两个碰巧在同一时间完成的线程尝试更新总和,并且只有其中一个有效)。

您可能还没有看到这个因为integralproc()函数的执行时间很长,因此多个线程同时达到更新*targ->resptr的可能性很低。

尽管如此,你仍然应该解决这个问题。您可以在总和更新周围添加互斥锁定/解锁:

pthread_mutex_lock(&result_lock);
*(targ->resptr) += res;
pthread_mutex_unlock(&result_lock);

(这不应该影响解决方案的效率,因为您只在每个线程的生命周期中锁定和解锁一次)。

或者,您可以让每个线程在其自己的线程参数结构中记录自己的部分结果:

targ->result = res;

然后,一旦工作线程全部被pthread_join()ed创建它们的父线程就可以遍历所有线程参数结构并添加部分结果。

这里不需要额外的锁定,因为工作线程不会访问彼此的结果变量,并且pthread_join()在设置结果的工作者和读取它的父线程之间提供必要的同步。

© www.soinside.com 2019 - 2024. All rights reserved.