Google Interview Question
Developer Program Engineersvoid AllowMany() {
// in the time I'm doing allow one I do not want anybody getting in, so I'll wait here
// otherwise just aquire and release
mutex.Acquire();
mutex.Release();
semaphore.Acquire();
...allowmany code comes here
semaphore.Release();
}
void AllowOne()
{
mutex.Acquire();
// first wait everybody to get out of the allow many because I don't want to //release something that was aquired by the aloow many and vice versa
while (semaphore_count>0)
Thread.wait(100);
// now my critical section, I now that nobody is in allow many and nobody can get in
mutex.Release();
}
In the method , where more than one thread can be allowed , use semaphore for sync ..
fun1() // where only one thread is allowed..
{
Createthread // single thread ..
}
fun2()
{
{
semaphore obj(count);
// create number of threads
createthread();
}
}
criticalsectioncode()
{
waitforsingleobject(mutexhandle)
waitformultipleobjects(semaphore)
}
Threadproc1 // for mutex
{
// access critical section code
}
Threadproc2 // forsemaphore
{
// access critical section code
}
Seems to me like a reader writer problem. Second method is writer equivalent, first method is reader equivalent.
void AllowMany()
{
semaphore.Acquire();
// Critical section
semaphore.Release();
}
void AllowOne()
{
int n = 0;
while (n < semaphore_count)
{
semaphore.Acquire(); // This shall lock all threads from accessing AllowMany
}
// Critical section
while (n > 0)
{
semaphore.Release();
}
}
Note the two loops in AllowOne. This ensures there is no starvation between readers and writers. In essence you won't need to use a mutex !
MAX_READERS = 32;
Semaphore semaphore = new Semaphore(MAX_READERS);
void Read() {
...
semaphore.acquire();
read();
semaphore.release();
...
}
void Write() {
...
mutex.lock();
for (int i = 0; i < MAX_READERS; ++i)
semaphore.acquire();
mutex.unlock();
write();
semaphore.release(MAX_READERS);
...
}
AllowOne is waiting on the mutex when all the AllowMany get out and vice versa.
I call it read write mutex because it is similar to the problem when you allow many readers but only writer to access the critical section. You can use it in the provided class or any place you'd find a similar issue
class ReadWriteMutex
{
public:
ReadWriteMutex(unsigned readers):
maxreaders(readers), s(maxreaders), nreaders(0),writeRequest(FALSE)
{
};
void ReadAccess()
{
while(1)
{
m_internal.Aquire();
unsigne t = writeRequest;
if (!writeRequest)
{
if ( nreaders++ == 0)//first reader comes
m_read.Acquire();
m_internal.Release()
break;
}
m_internal.Release();
if (t)
{
m_read.Acquire();
m_read.Release();
}
}
{
s.Acquire();
}
}
void WriteAccess()
{
while(1)
{
m_internal.Aquire();
writeRequest = TRUE;
unsigned n = nreaders;
if (!nreaders) //no mo readers - the CS is exclusively locked for the writer.
{
m_read.Acquire();
m_internal.Release();
break;
}
m_internal.Release();
if (n)
{
m_read.Acquire();
m_read.Release();
}
}
}
void ReadExit()
{
m_internal.Aquire();
s.Release();
nreaders--;
if (!nreaders)
m_read.Release();
m_internal.Release();
}
void WriteExit()
{
m_internal.Aquire();
writeRequest = FALSE;
m_read.Release();
m_internal.Release();
}
private:
unsigned maxreaders;
Semaphore s;
Mutex m_read,
m_internal;
unsigned nreaders;
bool writeRequest;
};
I would do this way, though i feel this might not be correct. semaphores are used to signal conditions
class ClassThatNeedsFixing
{
Mutex m;
Semaphore s;
int count;
public:
ClassThatNeedsFixing(int count): m(), s(count), count(count)
{}
void AllowMany(void)
{
m.acquire();
s.acquire();
m.release();
// whatever you wanna do
s.release();
}
void AllowOne(void)
{
m.acquire();
int n = count;
while(n > 0 )
{
s.acquire();
n--;
}
// i am gonna block all
n = count;
while(n>0)
{
s.release();
n--;
}
m.release();
}
}
// Using semaphone and mutex in AllowMany function and Using mutex in AllowOne function
void AllowMany() {
if(semaphore_count == 0) mutex.Acquire();
semaphore_count ++;
// Here is the critical section that must be protected
semaphore_count ++;
if(semaphore_count == 0) mutex.Release();
}
// Will lock out any client, including callers to the other method.
void AllowOne() {
mutex.Acquire();
// Here is the critical section that must be protected
mutex.Release();
}
Sorry in my code above AllowOne needs a mutex as well:
This is so because multiple threads can also access AllowOne at the same time.
- Ashish Kaila August 11, 2011