coachabower
2012-04-18 19:39:09 UTC
I'm trying to wrap my head around the idea of true concurrency. Say we take the reader preference route. In order to signal the writer when the reader que is empty, we would need to track how many readers are in que.
To allow true concurrency we would not want to block access to the shared memory by any reader unless a que maximum was reached or the writer was active. In this case, when checking the amount of readers in que, we could see zero in one reader thread and signal the writer, but possibly have another reader access the memory before the writer gets time on the processor, thereby allowing a reader to access the memory at the same time the writer is writing to it.
In the example implementations I've seen, most people seem to surround the reader critical areas with a mutex. While this does provide a solution to the reader writer simultaneous access issue, it also seems to me eliminate true concurrency. When the implementations mentioned above run, really only one thread can read at a time.
So my question is, what can I do that will preserve true concurrency, but still allow me to block all reader threads when a writer is active?
I actually may have thought of something, but I'm going to post this to get your thoughts in case I'm wrong or just to see if there's a better way. My plan is a simple global variable, set it to 1 when the writer is active, reader when entering critical section reads if var is 0, skips if 1(writer active).
My set up:
WRITER:
sem_wait(&mutex);
critical section;
sem_signal(&readers);
READER:
sem_wait(&spaces);
sem_signal(&readers);
readCounter++;
critical;
readcounter--;
if (readCounter == 0) sem_signal(&mutex);
sem_wait(&readers);
sem_signal(&spaces);
mutex is initialized to 0 and blocks WRITER until a signal arrives from READER indicating the reader que is empty.
readers is initialized to 0 and incremented when READER begins, decremented when it ends.
spaces is used to control the maximum concurrent readers allowed, initialized to user preference, I arbitrarily chose 7. When READER starts spaces is decremented, when it ends it gets incremented.
This implementation seems to do a good job of preserving the integrity of concurrency among readers, but the issue I presented arises when the counter is being checked in one thread where the value will show 0, while at the same time another thread is entering the critical area, meaning it will have already signaled the readers semaphore. When the first thread sees 0 as the counter value it signals the writer, after which it should call the wait function on the readers semaphore, which if the que were truly empty the semaphore would block at this call. Since another thread can and likely is running in the critical section, the semaphore has already been signaled, preventing the block that should occur.
Basically the readers never really stop, or could in some cases, not in others, but unpredictable. This is the dilemma, true concurrency is unpredictable. Hmm...hopefully someone out there can help me through this, no pun intended, "writers block."