C语言中的多进程和线程同步与排序
我试图完成的是在每个新进程中创建3个进程和一个新线程,以处理匿名映射的共享内存。我还不熟悉多线程和IPC,所以可能我没有正确使用它们,但我尝试了互斥、信号量和条件变量,当我接近在它们之间传递内存时,它要么挂起,要么似乎没有完全传递信息 我想做的是:C语言中的多进程和线程同步与排序,c,multithreading,process,pthreads,ipc,C,Multithreading,Process,Pthreads,Ipc,我试图完成的是在每个新进程中创建3个进程和一个新线程,以处理匿名映射的共享内存。我还不熟悉多线程和IPC,所以可能我没有正确使用它们,但我尝试了互斥、信号量和条件变量,当我接近在它们之间传递内存时,它要么挂起,要么似乎没有完全传递信息 我想做的是: 第一个fork()进程创建一个线程并从文件中读入 第二个进程是创建一个新线程来处理共享内存以改变它 第三个进程创建一个线程,再次改变共享内存,然后将其输出到文件 我知道我可以通过一个管道和3个进程来实现这一点,但我想尝试一下共享内存和线程 是否可以按
- 第一道工序->第一道工序->第二道工序->第二道工序->第三道工序->第三道工序
更新的问题:我发现当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和一些细微的修改,我找到了一个解决方案。我基本上按照进程顺序对调用的线程重新排序。我没有使用信号量,而是让父线程等待其子线程完成。所以