Reputation: 1
basically my program has 2 sets of threads, workers and jobs. Each job has an arrival time, then it is pushed onto a queue.
For the servers, I want them to constantly look for a job on the queue, once there is a job on the queue, only 1 worker takes it off and does its thing with it.
In main, all the worker threads are created first and then the job threads are created and synchronized (each pushing stuff on the queue). I can't get the timing right as the worker threads sometimes do things at exactly the same time OR the jobs aren't being pushed onto the queue at the right times (ie. job with arrival time 3 is pushed before job with arrival time 2). How can I do this using semaphores and/or mutexes?
I tried to put a mutex in the worker function but I don't really have a good handle on mutexes/semaphores..
Any ideas would be appreciated.
Thanks!
Upvotes: 0
Views: 295
Reputation: 4863
Copied from an answer to one of my earlier questions. My question concerns Win32 threads but the described consept pretty much the same with pthreads.
sem_post()
to increment the count associated with the semaphoresem_wait()
on the handle of your semaphore objectHere is a tutorial for POSIX Semaphores
But first like the other guy said, you have to make Q thread-safe.
void *func(void *newWorker) {
struct workerType* worker = (struct workerType*) newWorker;
while(numServed < maxJobs) {
//if(!Q.empty()) {
// No need to ask if Q is empty.
// If a thread passes the sem_wait function
// there has to be at least one job in the Q
sem_wait(&semaphore);
pthread_mutex_lock(&mutex);
struct jobType* job = Q.front();
numServed++;
cout << job->jobNum << " was served by " << worker->workerNum << endl;
Q.pop();
pthread_mutex_unlock(&mutex);
//sleep(worker->runTime); No need to sleep also
//}
}
}
void *job(void *jobdata) {
struct jobType *job = (struct jobType*) jobdata;
//sleep(job->arrivtime);
pthread_mutex_lock(&mutex);
Q.push(job);
pthread_mutex_unlock(&mutex);
sem_post(&semaphore);
// Inform the workers that another job is pushed.
}
Upvotes: 1
Reputation: 601
The Q push to Q pop operation needs to be atomic i.e (is the Critical section). Put that under a Mutex acquire and Mutex release. That should do it for you.
Check the posix thread tutorial to understand mutex acquisition and release. I use this PTHREAD TUTORIAL
Upvotes: 1
Reputation: 126203
The problem is that your servers are doing three non-atomic queue operations (empty, then front, then pop) with no synchronization to ensure that some other thread doesn't interleave its operations. You need to acquire a mutex or semaphore before calling Q.empty and release it after calling Q.pop to ensure that the empty/front/pop trio is done atomically. You also need to make sure you release the mutux properly if Q.empty fails
Upvotes: 0