与信号量同步
Synchronization with semaphores
此程序在共享内存上运行。它创建 4 child 个进程,将共享内存中的 int 值(最初为 0)递增到 MAXCOUNT(此处为 100k)。
当 child 发现共享内存中的 int 值等于 MAXCOUNT 时,它停止递增它。有时有效,共享内存中的int值正好是MAXCOUNT,有时是上面的1或2。
我最后的输出是:
Process 3 incremented value by 24138.
Process 2 incremented value by 26471.
Process 1 incremented value by 23247.
Process 0 incremented value by 26145.
Shared Memory = 100001, MAXCOUNT = 100000
超出限制 1。
这怎么可能,又该如何解决?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#include <semaphore.h>
#define MAXCOUNT 100000
#define NUM_CHILDREN 4
#define SHMSEGSIZE sizeof(int)
int main(){
int i, shmID, *shared_mem, count = 0;
int pid[NUM_CHILDREN];
shmID = shmget(IPC_PRIVATE, SHMSEGSIZE*2, IPC_CREAT | 0644);
shared_mem = (int *)shmat(shmID, 0, 0);
*shared_mem = 0;
sem_t *mysem = (sem_t*)(shared_mem+1);
sem_init(mysem, 1, 1);
for (i=0; i < NUM_CHILDREN; i++) {
pid[i] = fork();
if (pid[i] == -1) { return EXIT_FAILURE; }
if (pid[i] == 0) {
/* problem here */
while (*shared_mem < MAXCOUNT) {
sem_wait(mysem);
*shared_mem += 1;
sem_post(mysem);
count++;
}
/* problem here */
printf("Process %i incremented value by %i.\n", i, count);
shmdt(shared_mem);
return EXIT_SUCCESS;
}
}
for (i=0; i < NUM_CHILDREN; i++) {
waitpid(pid[i], NULL, 0);
}
printf("Shared Memory = %i, MAXCOUNT = %i\n", *shared_mem, MAXCOUNT);
shmdt(shared_mem);
shmctl(shmID, IPC_RMID, 0);
return EXIT_SUCCESS;
}
编辑:
我将问题部分更改为:
while (1) {
sem_wait(mysem);
if(*shared_mem < MAXCOUNT){
*shared_mem += 1;
}else{
break;
}
sem_post(mysem);
count++;
}
但现在我想我产生了一个死锁,因为我的输出是这样的:
Process 2 incremented value by 23775.
在您的代码中,您正在检查 *shared_mem < MAXCOUNT
锁定部分之外 。
while (*shared_mem < MAXCOUNT) {
/* XXX: other threads have a chance to change shared_mem before you lock. */
sem_wait(mysem);
*shared_mem += 1;
sem_post(mysem);
count++;
}
您应该重构您的代码,以便将检查包含在临界区内。
编辑
根据评论和编辑过的问题:您的新代码在未解锁信号量的情况下中断。其他线程仍然卡住。
the posted code has the following loop,
which is checking the value of shared_mem, Then waiting
During that wait, another child process could/will increment shared_mem
Then this child increments shared_mem
the result is over counting
while (*shared_mem < MAXCOUNT)
{
sem_wait(mysem);
*shared_mem += 1;
sem_post(mysem);
count++;
}
suggest:
do
{
sem_wait(mysem);
if( *shared_mem < MAXCOUNT )
{
*shared_mem++;
}
sem_post(mysem);
count++;
} while( *shared_mem <MAX_COUNT );
此程序在共享内存上运行。它创建 4 child 个进程,将共享内存中的 int 值(最初为 0)递增到 MAXCOUNT(此处为 100k)。
当 child 发现共享内存中的 int 值等于 MAXCOUNT 时,它停止递增它。有时有效,共享内存中的int值正好是MAXCOUNT,有时是上面的1或2。
我最后的输出是:
Process 3 incremented value by 24138.
Process 2 incremented value by 26471.
Process 1 incremented value by 23247.
Process 0 incremented value by 26145.
Shared Memory = 100001, MAXCOUNT = 100000
超出限制 1。 这怎么可能,又该如何解决?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#include <semaphore.h>
#define MAXCOUNT 100000
#define NUM_CHILDREN 4
#define SHMSEGSIZE sizeof(int)
int main(){
int i, shmID, *shared_mem, count = 0;
int pid[NUM_CHILDREN];
shmID = shmget(IPC_PRIVATE, SHMSEGSIZE*2, IPC_CREAT | 0644);
shared_mem = (int *)shmat(shmID, 0, 0);
*shared_mem = 0;
sem_t *mysem = (sem_t*)(shared_mem+1);
sem_init(mysem, 1, 1);
for (i=0; i < NUM_CHILDREN; i++) {
pid[i] = fork();
if (pid[i] == -1) { return EXIT_FAILURE; }
if (pid[i] == 0) {
/* problem here */
while (*shared_mem < MAXCOUNT) {
sem_wait(mysem);
*shared_mem += 1;
sem_post(mysem);
count++;
}
/* problem here */
printf("Process %i incremented value by %i.\n", i, count);
shmdt(shared_mem);
return EXIT_SUCCESS;
}
}
for (i=0; i < NUM_CHILDREN; i++) {
waitpid(pid[i], NULL, 0);
}
printf("Shared Memory = %i, MAXCOUNT = %i\n", *shared_mem, MAXCOUNT);
shmdt(shared_mem);
shmctl(shmID, IPC_RMID, 0);
return EXIT_SUCCESS;
}
编辑:
我将问题部分更改为:
while (1) {
sem_wait(mysem);
if(*shared_mem < MAXCOUNT){
*shared_mem += 1;
}else{
break;
}
sem_post(mysem);
count++;
}
但现在我想我产生了一个死锁,因为我的输出是这样的:
Process 2 incremented value by 23775.
在您的代码中,您正在检查 *shared_mem < MAXCOUNT
锁定部分之外 。
while (*shared_mem < MAXCOUNT) {
/* XXX: other threads have a chance to change shared_mem before you lock. */
sem_wait(mysem);
*shared_mem += 1;
sem_post(mysem);
count++;
}
您应该重构您的代码,以便将检查包含在临界区内。
编辑
根据评论和编辑过的问题:您的新代码在未解锁信号量的情况下中断。其他线程仍然卡住。
the posted code has the following loop,
which is checking the value of shared_mem, Then waiting
During that wait, another child process could/will increment shared_mem
Then this child increments shared_mem
the result is over counting
while (*shared_mem < MAXCOUNT)
{
sem_wait(mysem);
*shared_mem += 1;
sem_post(mysem);
count++;
}
suggest:
do
{
sem_wait(mysem);
if( *shared_mem < MAXCOUNT )
{
*shared_mem++;
}
sem_post(mysem);
count++;
} while( *shared_mem <MAX_COUNT );