Using semaphores in a parallel programming or multi user environment

Click For Summary

Discussion Overview

The discussion revolves around the implementation and behavior of semaphores in parallel programming, particularly focusing on the atomicity of operations within the P function and the implications of checking conditions multiple times. Participants explore the nuances of semaphore behavior in multi-threaded environments, addressing potential issues such as deadlocks and process context-switching.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Conceptual clarification

Main Points Raised

  • One participant questions whether the entire P function must be atomic or just the decrement operation, seeking clarification on the atomicity requirement.
  • Another participant asserts that only the decrement operation needs to be atomic, arguing that it does not make sense for the wait operation to be atomic with respect to other operations.
  • A participant expresses confusion about the necessity of checking and waiting twice for the semaphore count to be non-negative, asking for further explanation on how processes might disturb each other's requests.
  • Concerns are raised about process context-switching and the need for atomic operations to prevent race conditions and ensure proper synchronization among processes.
  • One participant proposes an alternative definition of the P function that omits the second wait, arguing that it could simplify the implementation, but others warn that this could lead to deadlocks.
  • Examples are provided to illustrate how deadlocks can occur if the semaphore count is not managed correctly, emphasizing the importance of the original definition of P.
  • There is a discussion about whether the atomicity of the entire P function could prevent deadlocks, with participants debating the implications of such a definition.
  • Some participants suggest that the Wikipedia article may assume additional synchronization methods that are not explicitly stated, leading to confusion in understanding the semaphore behavior.

Areas of Agreement / Disagreement

Participants express differing views on the atomicity of the P function and the necessity of multiple checks for the semaphore count. There is no consensus on the best approach to defining the P function or the implications of its current definition, indicating ongoing debate and uncertainty.

Contextual Notes

Limitations in understanding arise from the complexity of semaphore behavior in multi-threaded environments, particularly regarding the assumptions made in existing literature and the potential for deadlocks based on different implementations.

Eus
Messages
93
Reaction score
0
Hi Ho!

I read on http://en.wikipedia.org/wiki/Semaphore_(programming) that

P(Semaphore s, integer howmany)
{
wait until s >= 0;
s := s - howmany; /* must be atomic operation */
wait until s >= 0;
}

Must the whole function of P be atomic or just the "s := s - howmany;" part?
A pointer to a more detailed resource would help also.

Thank you very much.


Eus
 
Technology news on Phys.org
As I interpret what they've written there, they just mean that the decrement must be atomic. For one thing, atomic increment/decrement is a widely available synchronization primitive. For another thing, I don't see how it would make sense to say that a "wait" should be "atomic" with respect to some other operation in the first place.
 
Okay, I got it. Thanks.

Besides that, it is also written there that "the need of checking and waiting twice for the s >= 0 condition in P is needed to guarantee that as multiple processes are added to the semaphore's waiting list they do not disturb each other's request: a process does not change the semaphore's count until it is next in the queue."

I still don't get why a process will disturb the other if it changes the semaphore's count in its legitimate turn. Could you please give additional information? Or, maybe a pointer to a more detailed explanation?

Thank you very much.


Eus
 
It is a process context-switching issue. There is no guarantee about when a process or a thread will get/lose it's turn with the CPU. Atomic means the process will complete a subtraction, guaranteed, once it starts a subtraction. It cannot lose its turn with the CPU in the middle of making the subtraction.

Semaphores and mutexes are traffic cops, making threads or processes take turns one at a time when accessing an object or a critical section. So any change to a mutex has to complete, it cannot be left in an indeterminate state - its value has to be absolutely the same for any process that tests it, not 0 for me and 1 for you.
 
It is a process context-switching issue...

Semaphores and mutexes are traffic cops, ...

Yes, to avoid race condition and to enforce a certain order of execution (to perform synchronization).

But, it still does not explain why:
the need of checking and waiting twice for the s >= 0 condition in P is needed to guarantee that as multiple processes are added to the sempahore's waiting list they do not disturb each other's request: a process does not change the sempahore's count until it is next in the queue.

With other words, why doesn't P defined as:
Code:
P(Semaphore s, integer howmany)
{
    s := s - howmany; /* must be atomic operation */
    wait until x >= 0;
}
instead?

It is written there that:
In real implementations it is done without actually activating up the waiting process for the intermediate step.
Do you agree that it says about the new definition of P that I write above?

If you agree, then why even bother putting two waiting codes in the old definition of P and start making a long explanation, which I paste below, about it?
It should be noted that the semaphore count is not necessary equal to the buffers available in the pool. The need of checking and waiting twice for the s >= 0 condition in P is needed to guarantee that as multiple processes are added to the semaphore's waiting list they do not disturb each other's request: a process does not change the semaphore's count until it is next in the queue. In real implementations it is done without actually activating up the waiting process for the intermediate step.

The main thing is in the following sentence that is still greek to me:
... they do not disturb each other's request: a process does not change the semaphore's count until it is next in the queue.
Why "until it is next in the queue"? The scheduler picks a process at random, doesn't it?
In what way a process can change the semaphore's count before it is next in the queue if function P is the only way to change the semaphore's count?
In what way a process disturbs each other's request if the process does change the semaphore's count before it is next in the queue?

Could someone please help?

Thank you.


Eus
 
Eus said:
With other words, why doesn't P defined as:
Code:
P(Semaphore s, integer howmany)
{
    s := s - howmany; /* must be atomic operation */
    wait until x >= 0;
}
instead?
This is definitely bad -- it leads to deadlock. Consider the following: (the letters denote threads of execution)

The semaphorse is created with 3 permits.

A acquires 2 permits. The counter is now 1
B attempts to acquire 2 permits. The counter is now -1, and B sleeps.
C attempts to acquire 2 permits. The counter is now -3, and C sleeps.
A returns 2 permuts. The counter is -1.

Note that B and C can now never proceed; the counter is firmly locked at a negative value.


The example you originally gave in this post can demonstrate the same bad behavior -- e.g. if B and C both wake up from the first wait at the same time, and both do the decrement before the second check.


I think the Wikipedia article is implicitly making use of some additional synchronization method in their exposition. I'm going to complain on the discussion page.
 
This is definitely bad -- it leads to deadlock.

If suppose the whole function of P is atomic, can a deadlock occur?
Atomic means that once a thread is actively executing P, no other thread can execute P.
But, once a thread is sleeping waiting for its turn or it has reached the end of P, another thread can execute P.
Any objection to this atomic definition of P?

Anyway, even if P is atomic, a deadlock can still occur as follows :wink::

Consider the original code below:
Code:
P(Semaphore s, integer howmany) /*ATOMIC*/
{
    wait until s >= 0; /*first wait*/
    s := s - howmany;
    wait until s >= 0;/*second wait*/
}

Using your example, there will be a deadlock as follows:
The semaphore is created with 3 permits.

A acquires 2 permits. The counter is now 1
B attempts to acquire 2 permits. The counter is now -1, and B sleeps at 2nd wait.
C attempts to acquire 2 permits. C sleeps at 1st wait because the counter is -1.
A returns 2 permits. The counter is 1.
C wakes up to acquire 2 permits. The counter is now -1, and C sleeps at 2nd wait.
DEADLOCK!

I think the Wikipedia article is implicitly making use of some additional synchronization method in their exposition.

I think the article even does not say anything about that.
I cannot find a sentence that makes an allusion to it.

I'm going to complain on the discussion page.

Thank you for your help.


Eus
 

Similar threads

Replies
29
Views
6K
  • · Replies 5 ·
Replies
5
Views
4K
  • · Replies 5 ·
Replies
5
Views
4K
Replies
7
Views
10K
Replies
2
Views
3K
  • · Replies 16 ·
Replies
16
Views
7K
  • · Replies 4 ·
Replies
4
Views
10K
  • · Replies 8 ·
Replies
8
Views
7K
  • · Replies 175 ·
6
Replies
175
Views
28K