Can this pseudocode solve the dining philosopher problem with maximum parallelism? Here mutex is a binary semaphore initialized to 1. Forks are assumed to be numbered from 0 to (N-1). There are a total of N philosophers numbered from 0 to (N-1).
void philosopher(int i) // ith philosopher
{
while (true)
{
think();
down(&mutex); // acquire lock
take_fork(i); // take left fork
take_fork((i+1)%N); // take right fork
up(&mutex); // release the lock
eat();
down(&mutex); // acquire lock
put_fork(i);
put_fork((i+1)%N);
up(&mutex); // release the lock
}
}
This should solve the dining philosopher problem with maximum parallelism, because the lock is released after one philosopher has acquired both forks. But will it? And will there be any issue of liveliness? I am confused.
To answer your question I would like to provide a trace of events that seems to lead your philosophers into an undesired state.
Consider a system with N>2 philosophers Ph(0),...,Ph(N-1) and the following sequence of actions:
Ph(1).think();
Ph(0).think();
Ph(1).down(&mutex);
Ph(1).take_fork(1);
Ph(1).take_fork(2);
Ph(1).up(&mutex);
Ph(0).down(&mutex);
Ph(0).take_fork(0);
Ph(0).take_fork(1);
Recall that fork(1) is already acquired by Ph(1). Now depending on the semantics of take_fork() different behavior can occur.
If take_fork() fails immediately if the fork cannot be acquired, then fork(0) would never be released.
If take_fork() hangs until the resource is released, then the mutex would never be released and none of the other philosophers would be able to make progress therefore only one philosopher will be eating at a time.
Related
I have two threads using a common semaphore to conduct some processing. What I noticed is Thread 1 appears to hog the semaphore, and thread 2 is never able to acquire it. My running theory is maybe through compiler optimization/thread priority, somehow it just keeps giving it to thread 1.
Thread 1:
while(condition) {
mySemaphore->aquire();
//do some stuff
mySemaphore->release();
}
Thread 2:
mySemaphore->aquire();
//block of code i never reach...
mySemaphore->release();
As soon as I add a delay before Thread 1s next iteration, it allows thread 2 in. Which I think confirms my theory.
Basically for this to work I might need some sort of ordering aware lock. Does my reasoning make sense?
I'm trying to implement a multi-in multi-out interthread channel class. I have three mutexes: full locks when buffer is full. empty locks when buffer is empty. th locks when anyone else is modifying buffer. My single IO program looks like
operator<<(...){
full.lock() // locks when trying to push to full buffer
full.unlock() // either it's locked or not, unlock it
th.lock()
...
empty.unlock() // it won't be empty
if(...)full.lock() // it might be full
th.unlock()
operator>>(...){
// symmetric
}
This works totally fine for single IO. But for multiple IO, when consumer thread unlocks full, all provider thread will go down, only one will obtain th and buffer might be full again because of that single thread, while there's no full check anymore. I can add a full.lock() again of course, but this is endless. Is there anyway to lock full and th at same time? I do see a similar question about this, but I don't see order is the problem here.
Yes, use std::lock(full , th);, this could avoid some deadlocks
for example:
thread1:
full.lock();
th.lock();
thread2:
th.lock();
full.lock();
this could cause a deadlock, but the following don't:
thread1:
std::lock(full, th);
thread2:
std::lock(th, full);
No, you can't atomically lock two mutexes.
Additionally, it looks like you are locking a mutex in one thread and then unlocking it in another. That's not allowed.
I suggest switching to condition variables for this problem. Note that it's perfectly fine to have one mutex associated with multiple condition variables.
No, you cannot lock two mutexes at once, but you can use a std::condition_variable for the waiting threads and invoke notify_one when you are done.
See here for further details.
Functonality you try to achieve would require something similar to System V semaphores, where group of operations on semaphors could be applied atomically. In your case you would have 3 semaphores:
semaphore 1 - locking, initialized to 0
semaphore 2 - counter of available data, initialized to 0
semaphore 3 - counter of available buffers, initialized how much buffers you have
then push operation would do this group to lock:
check semaphore 1 is 0
increase semaphore 1 by +1
increase semaphore 2 by +1
decrease semaphore 3 by -1
then
decrease semaphore 1 by -1
to unlock. then to pull data first group would be changed to:
check semaphore 1 is 0
increase semaphore 1 by +1
decrease semaphore 2 by -1
increase semaphore 3 by +1
unlock is the same as before. Using mutexes, which are special case semaphores most probably would not solve your problem this way. First of all they are binary ie only have 2 states but more important API does not provide group operations on them. So you either find semaphore implementation for your platform or use single mutex with condition variable(s) to signal waiting threads that data or buffer is available.
I am having this weird issue with threads. On my mac with OS X this works fine but once I more it over to my desktop that is running Ubuntu, I am facing issues.
Essentially what I am doing is the following:
Function() {
for(i = 1 to 10)
while(array not completely changed) {
pthread_mutex_lock(&lock);
-- perform actions
pthread_mutex_unlock(&unlock);
}
}
}
And I have two threads running this function. While it is supposed to be running in such a manner that is:
Thread 1 grabs lock
performs opperations on array
Thread 1 releases lock
Thread 2 grabs lock
performs calculations on array
Thread 2 releases lock
and so on in a back and forth pattern until the array have been completed changed but on Linux all of the calculations of Thread 1 complete and then Thread 2 starts.
So I will get:
Thread 1 grabs lock
performs opperations on array
Thread 1 releases lock
Thread 1 grabs lock
performs calculations on array
Thread 1 releases lock
Thread 1 grabs lock
performs calculations on array
Thread 1 releases lock
And so on until the array is completely changed, once I increment the for loop, then Thread 2 will perform all calculations and continue this pattern.
Can anyone explain what is going on?
You're experiencing "starvation". Add a small nanosleep call occasionally to give the other threads a chance to run. Add the call outside the mutex pair (e.g. after the unlock). Thread 1 is monopolizing things.
You may also want to consider restructuring and splitting up the critical [requires locking] vs non-critical work:
while (more) {
lock ...
do critical stuff ...
unlock ...
nanosleep ...
do non-critical stuff
}
I've a question about the fairness of the critical sections on Windows, using EnterCriticalSection and LeaveCriticalSection methods. The MSDN documentation specifies: "There is no guarantee about the order in which threads will obtain ownership of the critical section, however, the system will be fair to all threads."
The problem comes with an application I wrote, which blocks some threads that never enter critical section, even after a long time; so I perfomed some tests with a simple c program, to verify this behaviour, but I noticed strange results when you have many threads an some wait times inside.
This is the code of the test program:
CRITICAL_SECTION CriticalSection;
DWORD WINAPI ThreadFunc(void* data) {
int me;
int i,c = 0;;
me = *(int *) data;
printf(" %d started\n",me);
for (i=0; i < 10000; i++) {
EnterCriticalSection(&CriticalSection);
printf(" %d Trying to connect (%d)\n",me,c);
if(i!=3 && i!=4 && i!=5)
Sleep(500);
else
Sleep(10);
LeaveCriticalSection(&CriticalSection);
c++;
Sleep(500);
}
return 0;
}
int main() {
int i;
int a[20];
HANDLE thread[20];
InitializeCriticalSection(&CriticalSection);
for (i=0; i<20; i++) {
a[i] = i;
thread[i] = CreateThread(NULL, 0, ThreadFunc, (LPVOID) &a[i], 0, NULL);
}
}
The results of this is that some threads are blocked for many many cycles, and some others enter critical section very often. I also noticed if you change the faster Sleep (the 10 ms one), everything might returns to be fair, but I didn't find any link between sleep times and fairness.
However, this test example works much better than my real application code, which is much more complicated, and shows actually starvation for some threads. To be sure that starved threads are alive and working, I made a test (in my application) in which I kill threads after entering 5 times in critical section: the result is that, at the end, every thread enters, so I'm sure all of them are alive and blocked on the mutex.
Do I have to assume that Windows is really NOT fair with threads?
Do you know any solution for this problem?
EDIT: The same code in linux with pthreads, works as expected (no thread starves).
EDIT2: I found a working solution, forcing fairness, using a CONDITION_VARIABLE.
It can be inferred from this post (link), with the required modifications.
You're going to encounter starvation issues here anyway since the critical section is held for so long.
I think MSDN is probably suggesting that the scheduler is fair about waking up threads but since there is no lock acquisition order then it may not actually be 'fair' in the way that you expect.
Have you tried using a mutex instead of a critical section? Also, have you tried adjusting the spin count?
If you can avoid locking the critical section for extended periods of time then that is probably a better way to deal with this.
For example, you could restructure your code to have a single thread that deals with your long running operation and the other threads queue requests to that thread, blocking on a completion event. You only need to lock the critical section for short periods of time when managing the queue. Of course if these operations must also be mutually exclusive to other operations then you would need to be careful with that. If all of this stuff can't operate concurrently then you may as well serialize that via the queue too.
Alternatively, perhaps take a look at using boost asio. You could use a threadpool and strands to prevent multiple async handlers from running concurrently where synchronization would otherwise be an issue.
I think you should review a few things:
in 9997 of 10000 cases you branch to Sleep(500). Each thread holds the citical section for as much as 500 ms on almost every successful attempt to acquire the critical section.
The threads do another Sleep(500) after releasing the critical section. As a result a single thread occupies almost 50 % (49.985 %) of the availble time by holding the critical section - no matter what!
Behind the scenes: Joe Duffy: The wait lists for mutually exclusive locks are kept in FIFO order, and the OS always wakes the thread at the front of such wait queues.
Assuming you did that on purpose to show the behavior: Starting 20 of those threads may result in a minimum wait time of 10 seconds for the last thread to get access to the critical section on a single logical processor when the processor is completely available for this test.
For how long dif you do the test / What CPU? And what Windows version? You should be able to write down some more facts: A histogram of thread active vs. thread id could tell a lot about fairness.
Critical sections shall be acquired for short periods of time. In most cases shared resources can be dealt with much quicker. A Sleep inside a critical section almost certainly points to a design flaw.
Hint: Reduce the time spent inside the critical section or investigate Semaphore Objects.
I am having trouble understanding why the first readers-writers problem can starve write processes, i.e.: how does the code provide reader processes with priority? Should the writer process not be able to gain a lock when one of the reader processes perform a signal(wrt)? Is it that the list for the semaphores is structured (as I can see how writers would be starved by a steady stream of reader processes in a LIFO list) in a way to give priority to reader processes or am I misunderstanding something fundamental here?
semaphore wrt=1,mutex=1;
readcount=0;
writer()
{
wait(wrt);
//writing is done
signal(wrt);
}
reader()
{
wait(mutex);
readcount++;
if(readcount==1)
wait(wrt);
signal(mutex);
///Do the Reading
///(Critical Section Area)
wait(mutex);
readcount--;
if(readcount==0)
signal(wrt);
signal(mutex);
}
If you always have 2 or more readers active, the signal(wrt) will never get called at the end of the reader block. New readers won't have readcount == 1 so they won't wait on wrt, but they'll increase the readcount. This makes unending read requests starve the writer thread. If the reader count ever gets to 0, then the wrt will be released and the writer can finally work. Until that point readers have priority.
This isn't a LIFO approach precisely, but rather priority queue where readers have priority.