使用文件锁的进程之间的条件变量

Posted

技术标签:

【中文标题】使用文件锁的进程之间的条件变量【英文标题】:condtional variable among processes using file lock 【发布时间】:2019-11-22 17:52:31 【问题描述】:

我想同步多个进程。我提出了两种可能的方法: 1.文件锁 2. 使用共享内存的进程间互斥

但是共享内存有点复杂,我不确定我是否可以使用它而不会对我的进程中运行的其他模块产生副作用。所以我更喜欢文件锁的方式。

但是文件锁只提供shared lockexclusive lock,没有条件变量(据我所知..)。有没有其他方法可以这样做?还是我别无选择,只能共享内存?

添加:

我想要一个条件变量的原因是我想限制共享锁持有者的数量

我想出了一个方法,只使用一个简单的独占文件锁,如下面的伪代码所示:

RETRY:
file_lock.unique_lock();
if (counter == MAX_PROCESS_ALLOW) 
  file_lock.unlock();
  goto RETRY;

// successful get into the pool
++counter;
file_lock.unlock();

// do some thing here

// exit the pool
file_lock.unique_lock();
--counter;
file_lock.unlock();

但是这种方法的问题是查询繁忙。或者我可以选择睡觉,但是睡眠时间很难确定......

【问题讨论】:

你能解释一下你的实际问题是什么吗?为什么流程需要同步?你想阻止什么事情发生? 另见信号量 @DavidSchwartz 他们是一些工作进程,他们会不时运行一些消耗CPU的任务(当有人将任务提交给那些进程时),并且我系统中还有其他进程在运行,所以我想限制运行任务的活动工作进程的最大数量,这样它们就不会从其他进程中占用太多的计算资源。 @ZiqiLiu 你的操作系统不提供一些工具吗?这似乎是操作系统最好的做法,因为它实际上知道还有什么在争夺资源。 @DavidSchwartz 你的意思是调整进程优先级吗?我正在使用 Ubuntu 16。 【参考方案1】:

考虑使用,

sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
int sem_wait(sem_t *sem);
int sem_getvalue(sem_t *sem, int *sval);
int sem_post(sem_t *sem);
int sem_close(sem_t *sem);
int sem_unlink(const char *name);

任何有权限的进程都可以修改计数,这将释放等待锁的进程。这将允许进行复杂的评估。在 sem_open(...) 中设置“值”,将确定可以共享锁的进程数。有关详细信息,请参见手册页。有许多支持功能。以下代码是一个示例。如果您构建并执行它超过 4 次,那么您将看到后期启动器等到早期启动器完成。

注意 /dev/shm/sem.test_sem 是 Debian Buster 下与 Linux 内核的共享资源。代码示例如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>

// For Debian Buster, the shared sem is found at /dev/shm/sem.test_sem

int main(int argc, char *argv[])
   printf("Starting\n");

    sem_t *sem;
    sem = sem_open("/test_sem", O_CREAT, 0600, 3);q
    if(sem == SEM_FAILED)
        printf("SEM_FAILED\n");
        return -1;
    
    // sem_unlink("/test_sem"); return 0;  // Use this to remove /dev/shm/sem.test_sem
    sem_wait(sem);
    for(int i = 0; i < 20 ; i++)
        int current_sem_value;
        int error_code = sem_getvalue(sem, &current_sem_value);
        //printf("sem_getvalue return value: %d\n", error_code);
        if(error_code)
            printf("Sem not valid!\n");
        
        printf("Sem count: %d \n", current_sem_value);
        fflush(stdout);
        sleep(1);
    

    sem_post(sem);
    sem_close(sem);

    return 0;

请注意,sem_unlink(...) 将从文件系统中删除一个信号量。

【讨论】:

以上是关于使用文件锁的进程之间的条件变量的主要内容,如果未能解决你的问题,请参考以下文章

条件变量和互斥锁的使用

使用条件变量优于互斥锁的优点

Linux进程间通信(互斥锁、条件变量、读写锁、文件锁、信号灯)

在无锁实现中没有互斥锁的条件变量

Go36-27,28-条件变量

Golang 锁和条件变量