Eag*_*One 9 c multithreading multiprocess
我正在编写一个启动两个进程的程序.
第一个进程,"客户端"发送两种类型的消息.
第一种类型增加了共享资源(int).第二种类型将资源设置为0.
在10条消息之后,客户端必须发送一个特殊类型的消息,该消息强制侦听两个队列的线程停止.因此,客户端在类型字段中发送两条带有特殊值的消息(每个队列一个),以终止线程.
第二个过程是"服务器".
服务器有三个线程:
第一个是监听"增加"队列.它必须处理增加请求,直到终止消息.所以我写道:
do{
msgrcv(id_i,&msg,dimensione,INCREMENTA,0);
pthread_mutex_lock(&mutex);
printf("THREAD 1: Il contatore vale:%d\n",*contatore);
incremento = msg.contenuto;
printf("THREAD 1: Incremento di : %d\n",incremento);
*contatore+=incremento;
printf("THREAD 1: Il contatore vale:%d\n",*contatore);
pthread_mutex_unlock(&mutex);
msgrcv(id_i,&msg,dimensione,TERMINA,IPC_NOWAIT); //IPC_NOWAIT or the thread will
freeze after the first message
}
while(msg.tipo!=TERMINA);
Run Code Online (Sandbox Code Playgroud)
第二个必须处理"设置为0"请求,直到终止消息.
do{msgrcv(id_a,&msg,dimensione,AZZERA,0);
pthread_mutex_lock(&mutex);
printf("THREAD 2: IL CONTATORE VALE:%d\n",*contatore);
*contatore=0;
printf("Thread 2: Contatore azzerato. Ora vale : %d\n",*contatore);
pthread_mutex_unlock(&mutex);
msgrcv(id_a,&msg,dimensione,TERMINA,IPC_NOWAIT);//IPC_NOWAIT or the thread will
freeze after the first message
}
while(msg.tipo!=TERMINA);
Run Code Online (Sandbox Code Playgroud)
第三个线程使用互斥锁增加资源的值以进入互斥.
问题是服务器进程的thread1和thread2没有终止它们应该的位置.事实上,他们在所有增加/ set0消息之后停留在第一个msgrcv()上.所以问题是两个线程无法管理监听终止消息.
我试图为第一个msgrcv设置IPC_NOWAIT但是没有用
你依靠的是竞争条件,你几乎永远不会赢.
我们来看看第一个块:
do {
// Note the msg type: vvvvvvvvvv
msgrcv( id_i, &msg, dimensione, INCREMENTA, 0 );
// ...
// Note the msg type: vvvvvvv
msgrcv( id_i, &msg, dimensione, TERMINA, IPC_NOWAIT );
}
while( msg.tipo != TERMINA );
Run Code Online (Sandbox Code Playgroud)
循环中的第二个"msgrcv"调用是您尝试查找终结符消息类型,然后循环回到顶部并阻塞,等待另INCREMENTA一条消息.
考虑以下事件链:
Sender Receiver
--------------- -----------------
1 Call msgrcv with INCREMENTA. Block indefinitely
2 Send 'INCREMENTA'
3 msgrcv returns. Begin processing increment msg.
4 Processing finshed.
5 Call msgrcv with TERMINA.
6 No TERMINA message found (queue empty), returns immediately.
7 Go to top of loop.
8 Call msgrcv with INCREMENTA. Block indefinitely
9 Send 'TERMINA'
10 Nothing happens because we're waiting for 'INCREMENTA'.
Run Code Online (Sandbox Code Playgroud)
您无法尝试以此模式查询消息队列.如果事件8和9被颠倒过来,那么你的逻辑就会发生 - 但这是一种竞争条件,而且你可能经常会失败.
相反,为什么不使用msgrcv接收任何类型的消息,然后在从队列中读取消息后,找出你得到的消息类型并从那里处理它.如果你传递0'msgtyp'参数msgrcv,它会给你所有的消息,然后你可以随意处理它.
while(true) {
// Get any msg type: vv
msgrcv( id_i, &msg, dimensione, 0, 0 );
if ( msg.tipo == TERMINA ) {
break;
}
else {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)