1

我有两个信号量应该原子地改变。

  union semun su;
  struct sembuf sb[2];
  int num = 2;

  semid = semget(num, 3, IPC_CREAT | IPC_EXCL | 0600);

  su.val = 1;
  semctl(semid, 0, SETVAL, su);
  su.val = 0;
  semctl(semid, 1, SETVAL, su);

  sb[0].sem_num = 0;
  sb[0].sem_op  = 1; // signal
  sb[0].sem_flg = 0;

  sb[1].sem_num = 1;
  sb[1].sem_op  = -1; //wait
  sb[1].sem_flg = 0;

  semop(semid, sb, 2)

如您所见,一个信号量应该signal(),另一个应该wait()

我在这个问题中读到,如果两个信号量同时更改,并且如果有一个信号量被阻塞,那么它并不会真正改变另一个信号量 - 并且所有信号量都将进入睡眠状态。

在我的实施中,对我来说非常重要的是:

  1. 两个信号量的操作都将原子地发生
  2. 如果第二个信号量将被阻塞,则对第一个信号量无关紧要。意味着第一个信号量将按signal()预期进行,第二个信号量将wait()...

我无法从附加的问题中理解是否可以这样做,而且我不确定那里是否有答案......

所以想问问有没有可能

提前谢谢

4

2 回答 2

1

我在这个问题中读到,如果两个信号量同时更改,并且如果有一个信号量被阻塞,那么它并不会真正改变另一个信号量 - 并且所有信号量都将进入睡眠状态。

问题涉及的是信号量操作集是否以原子方式发生。答案正确地澄清了它是原子的。

而不是这样想

“如果两个信号量同时改变”

这样看

“如果两个信号量都更改为一个

我敢肯定,你会欣赏原子性的概念。

很明显在上面的代码中这样做

semop(semid, sb, 2)

无论您的意图是什么,都将信号量 sb[0] 和 ab[1]的操作作为单个操作执行。

于 2013-03-01T21:59:16.663 回答
0

首先,您的代码示例不正确,没有多大意义。它应该是:

sb[0].sem_num = 0;
sb[0].sem_op = 1; // signal
sb[0].sem_flg = 0;

sb[1].sem_num = 1;
sb[1].sem_op = -1; //wait
sb[1].sem_flg = 0;

semop(semid, sb, 2)

您所描述的是可能的,这只是 2 个顺序操作:

sb[0].sem_num = 0;
sb[0].sem_op = 1; // signal
sb[0].sem_flg = 0;
semop(semid, sb, 1)

sb[0].sem_num = 1;
sb[0].sem_op = -1; // wait
sb[0].sem_flg = 0;
semop(semid, sb, 1)

在评论中讨论之后,看起来这个问题可以改写成这样:我可以让 semop() 原子操作部分原子化吗?不,你不能,它是原子的。如果您不需要多个操作是原子的,请不要将它们放在一个 semop() 中。

于 2013-03-01T21:55:24.737 回答