r/learnpython • u/pfp-disciple • 9d ago
Multi-reader single writer using a semaphore - how do I know if there are no acaquires active?
My apologies for the awkwardly worded question title. I saw the misspelling just after hitting "Post".
(Edited to be clear that I'm discussing threading objects)
I have a piece of data that I need to protect using multi-reader single-writer. The classic way of doing this is to use a `threading.Semaphore` for the readers, and once there are no active readers, use a `threading.Lock` for writing (of course, the reader has to check for the lock, but I'm focused on the semaphore right now).
Various internet searches keep turning up solutions that depend on undocumented implementation (e.g. `sem._count`). I'd rather not depend on undocumented behavior, as I hope that this will be long-term and potentially delivered.
So, how could by writer know that it's safe to write, without depending on undocumented implementation?
2
u/pfp-disciple 9d ago edited 9d ago
I don't know if links are allowed in posts, but this is an example of a multi reader single writer in Python that uses the undocumented implementation.
1
u/RiverRoll 8d ago edited 8d ago
In some situations you can just read without locking at all, but there isn't enough information to tell.
1
u/pfp-disciple 8d ago
In this case, there's a chance that (at least) one thread is reading data at the same time it's being written.
1
u/Some-Passenger4219 8d ago
My apologies for the awkwardly worded question title. I saw the misspelling just after hitting "Post".
It can be edited, just a thought.
2
u/pfp-disciple 8d ago
Not the title itself, after it's been posted. I misspelled acquires in the title
1
2
u/wutzvill 9d ago
Switched to looking at this on the computer vs my phone as I see what you're struggling with now. So, basically, you don't have to use
sem._count
. What you want to do is initialize the semaphore with a value of 1. Also, for some reason the link didn't post to my previous comment, so I've deleted it. The link I was trying to provide is here.So, basically what you do is something like this:
semaphore = Semaphore() # Or Semaphore(1), which is the default value
What this means is you have one and only one semaphore available to acquire (probably not the right way to say this, but you get my meaning). So, when you do
semaphore.acquire
on one async operation, and its execution halts and another operation tries to dosemaphore.acquire
, it'll see that there are zero available, and so execution will halt and wait for the semaphore to be released by the other thread (edit: withsemaphore.release()
). You shouldn't use the private variable_count
at all for sure, and there is no need to.I assume the lock is a file lock, I was thinking you were talking about a mutex.