In fact, multithreaded synchronization in general is non-idempotent. You don't want to send a synchronize signal twice, you need to send it exactly as many times as necessary. (Ex: mutex lock / unlock, which is probably the simplest version of a sempahore that you can get. Semaphore of size 1)
Agreed, though I think the GP was looking for a situation you can't refactor into becoming idempotent. Increments and decrements like traditional semaphores are definitely not idempotent, but couldn't you make an idempotent semaphore by changing the signature to be increment/decrement(source, from, to), such that it only applies the operation if the current state is equal to from, and the source is one particular subscriber? Then from the semaphore's perspective it's receiving a time series of messages some of which have the same identity, until all locks have been released and the owner gets notified.
> but couldn't you make an idempotent semaphore by changing the signature to be increment/decrement(source, from, to)
Think about a mutex lock: if the semaphore (aka: mutex) is already locked, your signature is: sem_wait(mutex, 0, 0).
Which is not idempotent. Two "sem_waits(s, 0, 0)" mean that you need two (other) threads to unlock you. One sem_wait(s, 0, 0) means that only one other thread needs to unlock you.
------
Semaphores used in this manner are how you implement reader/writer locks, as well as thread barriers. (If 100 threads are in existence, you wait for 100 semaphore_posts from those 100 other threads).
None of the semaphores or mutexes are idempotent. And never can be.
https://man7.org/linux/man-pages/man3/sem_post.3.html
-----
In fact, multithreaded synchronization in general is non-idempotent. You don't want to send a synchronize signal twice, you need to send it exactly as many times as necessary. (Ex: mutex lock / unlock, which is probably the simplest version of a sempahore that you can get. Semaphore of size 1)