Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的多进程和线程同步与排序_C_Multithreading_Process_Pthreads_Ipc - Fatal编程技术网

C语言中的多进程和线程同步与排序

C语言中的多进程和线程同步与排序,c,multithreading,process,pthreads,ipc,C,Multithreading,Process,Pthreads,Ipc,我试图完成的是在每个新进程中创建3个进程和一个新线程,以处理匿名映射的共享内存。我还不熟悉多线程和IPC,所以可能我没有正确使用它们,但我尝试了互斥、信号量和条件变量,当我接近在它们之间传递内存时,它要么挂起,要么似乎没有完全传递信息 我想做的是: 第一个fork()进程创建一个线程并从文件中读入 第二个进程是创建一个新线程来处理共享内存以改变它 第三个进程创建一个线程,再次改变共享内存,然后将其输出到文件 我知道我可以通过一个管道和3个进程来实现这一点,但我想尝试一下共享内存和线程 是否可以按

我试图完成的是在每个新进程中创建3个进程和一个新线程,以处理匿名映射的共享内存。我还不熟悉多线程和IPC,所以可能我没有正确使用它们,但我尝试了互斥、信号量和条件变量,当我接近在它们之间传递内存时,它要么挂起,要么似乎没有完全传递信息

我想做的是:

  • 第一个fork()进程创建一个线程并从文件中读入
  • 第二个进程是创建一个新线程来处理共享内存以改变它
  • 第三个进程创建一个线程,再次改变共享内存,然后将其输出到文件 我知道我可以通过一个管道和3个进程来实现这一点,但我想尝试一下共享内存和线程

    是否可以按如下方式对流程进行排序:

    • 第一道工序->第一道工序->第二道工序->第二道工序->第三道工序->第三道工序
    你会这样跑吗?对于N个进程和N个线程,通常有什么方法可以做到这一点?我觉得我应该可以,但我对这还不够熟悉。任何想法和建议都将不胜感激,提前感谢

    Edit:我在调用fork()中找到了解决方案,但在进程中重新排序了被调用的线程。查看下面的示例


    更新的问题:我发现当memcpy()在某个线程中运行时,我可以为一个缓冲区更新共享内存中的缓冲区,但不能为另一个缓冲区更新。在下一个线程中,我的一个缓冲区已满,但另一个缓冲区未满,即使快速检查表明在离开线程之前两个缓冲区中都有数据?我遇到了什么样的并发错误?感谢您的想法和建议,提前感谢

    这个问题相当普遍、广泛和深刻。 因此,我的回答将为您提供多线程/多处理的入门知识。 首先,我想把问题分为两个主要问题: 1) 单个进程内的线程同步。 2) 单线程进程同步。 稍后,您可以结合(1)和(2),不要忘记混合线程和分叉所引起的特殊问题和副作用

    1.线程同步。 让我们假设有一个进程有3个(一般情况下是M个)线程t1、t2和t3,它们应该以强顺序运行:t1、t2和t3。即使您完全按照这个顺序创建这些线程,也没有人能保证它们会按照这个顺序启动。您可以通过强制t2和t3等待两个条件变量(c1和c2)来阻止它们的执行。当t1和t2线程就绪时,上述条件变量将向t2和t3线程发送信号。t1线程将“解锁”c1变量,t2线程将“解锁”c2。 因此,您只需要两个(或M-1)条件变量,它们与两个(或M-1)互斥体和两个(或M-1)负责线程状态的布尔值关联。这是一个简化的代码。虽然它可以工作(您可以使用gcc-lpthread编译它),但您的“真实”代码应该将变量组织到结构中,检查错误等

    #include <pthread.h>
    #include <stdio.h>
    
    // These are mentioned mutexes, conditional variables and booleans.
    // They are global, so any thread can access them.
    pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t  c1 = PTHREAD_COND_INITIALIZER;
    int t1_is_ready = 0;
    
    pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t  c2 = PTHREAD_COND_INITIALIZER;
    int t2_is_ready = 0;
    
    // This function is invoked by the t1 thread.
    // It does not depend on conditional variables and always is executed first.
    // When it's ready it sets its ready status to one and signal to the thread t2
    // via c2, that the status has changed.
    void* t1_work(void* arg)
    {
      pthread_mutex_lock(&m1);
      printf("thread t1 does its work\n");
      t1_is_ready = 1;
      pthread_mutex_unlock(&m1);
      pthread_cond_signal(&c1);
    
      pthread_exit(NULL);
    } 
    
    // This function is invoked by the t2 thread.
    // It is blocked until t1 setis is ready status to 1.
    // Pay your attention how to wait on a conditional variable:
    // with locked mutex and in a loop, to prevent spurious wakes up. 
    void* t2_work(void* arg)
    {
      pthread_mutex_lock(&m1);
      while(t1_is_ready == 0)
      {
        pthread_cond_wait(&c1, &m1);
      }
      pthread_mutex_unlock(&m1);
    
      pthread_mutex_lock(&m2);
      printf("thread t2 does its work\n");
      t2_is_ready = 1;
      pthread_mutex_unlock(&m2);
      pthread_cond_signal(&c2);
    
      pthread_exit(NULL);
    }
    
    // This function is invoked by the t3 thread.
    void* t3_work(void* arg)
    {
      pthread_mutex_lock(&m2);
      while(t2_is_ready == 0)
      {
        pthread_cond_wait(&c2, &m2);
      }
    
      printf("thread t3 does its work\n");
      pthread_mutex_unlock(&m2);
    
      pthread_exit(NULL);
    }
    
    int main(void)
    {
      pthread_t t1;
      pthread_t t2;
      pthread_t t3;
    
      pthread_create(&t1, NULL, t1_work, NULL);
      pthread_create(&t2, NULL, t2_work, NULL);
      pthread_create(&t3, NULL, t3_work, NULL);
    
      pthread_join(t1, NULL);
      pthread_join(t2, NULL);
      pthread_join(t3, NULL);
    
      return 0;
    }
    
    #包括
    #包括
    //上面提到的是互斥体、条件变量和布尔值。
    //它们是全局的,因此任何线程都可以访问它们。
    pthread_mutex_t m1=pthread_mutex_初始值设定项;
    pthread_cond_t c1=pthread_cond_初始值设定项;
    int t1_为_就绪=0;
    pthread_mutex_t m2=pthread_mutex_初始值设定项;
    pthread_cond_t c2=pthread_cond_初始值设定项;
    INTT2_为_就绪=0;
    //此函数由t1线程调用。
    //它不依赖于条件变量,总是先执行。
    //当它准备就绪时,它将其就绪状态设置为1,并向线程t2发送信号
    //通过指挥与控制,状态已发生变化。
    void*t1_工作(void*arg)
    {
    pthread_mutex_lock(&m1);
    printf(“线程t1执行其工作\n”);
    t1_为_就绪=1;
    pthread_mutex_unlock(&m1);
    pthread_cond_信号(&c1);
    pthread_exit(NULL);
    } 
    //此函数由t2线程调用。
    //直到t1 setis就绪状态变为1,它才会被阻止。
    //请注意如何等待条件变量:
    //具有锁定的互斥锁并处于循环中,以防止虚假唤醒。
    无效*t2_工作(无效*arg)
    {
    pthread_mutex_lock(&m1);
    而(t1_为_就绪==0)
    {
    pthread_cond_wait(&c1和&m1);
    }
    pthread_mutex_unlock(&m1);
    pthread_mutex_lock(&m2);
    printf(“线程t2执行其工作\n”);
    t2_为_就绪=1;
    pthread_mutex_unlock(&m2);
    pthread_cond_信号(&c2);
    pthread_exit(NULL);
    }
    //此函数由t3线程调用。
    无效*t3_工作(无效*arg)
    {
    pthread_mutex_lock(&m2);
    而(t2_为_就绪==0)
    {
    pthread_cond_wait(&c2和&m2);
    }
    printf(“线程t3执行其工作\n”);
    pthread_mutex_unlock(&m2);
    pthread_exit(NULL);
    }
    内部主(空)
    {
    pthread_t t1;
    pthread_t t2;
    pthread_t t3;
    pthread_create(&t1,NULL,t1_work,NULL);
    pthread_create(&t2,NULL,t2_work,NULL);
    pthread_create(&t3,NULL,t3_work,NULL);
    pthread_join(t1,NULL);
    pthread_join(t2,NULL);
    pthread_join(t3,NULL);
    返回0;
    }
    
    2.进程同步 下面是一篇很好的文章,其中包含进程同步的代码示例:
    由于您计划通过fork()函数创建流程,因此它们将被称为“相关”。如果您有3个(或N个)正在运行的进程,则创建2个(N-1)信号量,并以同步线程的方式使用它们。

    多亏了@MichaelGoren和一些细微的修改,我找到了一个解决方案。我基本上按照进程顺序对调用的线程重新排序。我没有使用信号量,而是让父线程等待其子线程完成。所以

  • 我为我的第一个进程调用了fork(),并告诉父进程等待它的子进程。我在这个叉和下一个叉之间也有一根管子()。我打电话给我的第三个线程在这个家长