1

I'm starting my studies with syncronzed threads using semaphore.
I just did a test using binary semaphore (2 threads only) and it's all good.

Imagine a lanhouse, that have 3 computers (threads) and some clients (Threads). If all computers are bussy, the client will wait in a queue with a know limit (e.g 15 clients).

I can't understand how threads will relate to each other.

As far as I know, semaphore is used to control the access of the threads to a certain critical region / memory area / global variable.

1) Create 1 semaphore to control the Clients accessing the computers (but both are threads);

2) Create 1 semaphore to control the clients in queue;

But how relate threads with threads ? How the semaphore will know which thread(s) it should work with.

I don't need a full answer for it. I just need to understand how the Threads will relate to eachother. Some help to understand the situation.

This is my code so far and it's not working ;P can't control the clients to access the 3 computers avaliable.

#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define ROOM_SIZE 15

sem_t queue, pc, mutex;
int room [ROOM_SIZE];
int pcsAvaliable = 3, nAvaliable = 0, roomAvaliable = ROOM_SIZE;
int computers [3]; // 0 -> Empty  | 1 -> Ocuppied

void* Lan(void* arg)
{
    //Enter the lanhouse
    //Verify if there is a computer avaliable
    sem_wait(&pc);

    if(pcsAvaliable > 0)
    {
        sem_wait(&mutex);
        pcsAvaliable--;
        computers[nAvaliable] = 1;      
        printf("Cliente pegou pc: %d\n", nAvaliable);
        nAvaliable++;
        sem_post(&mutex);

        //Wait for 80~90ms
        printf("Client liberou pc: %d\n", nAvaliable);
        computers[nAvaliable] = 0;
        nAvaliable--;

        sem_post(&pc);
    }
    else
    {
        printf("No computer avaliable...\n");
        //Check the waiting room for avaliable slot
        if(roomAvaliable > 0)
        {
            roomAvaliable--;
            printf("Client entered the waiting room.");
        }
        else
            printf("No avaliable space in waiting room..\n");
    }



}

int main(int argc, char const *argv[])
{
    int i;

    if(argc > 1)
    {
        int numClients = atoi(argv[1]);
        sem_init(&pc, 0, 3);
        sem_init(&mutex, 0, 1);
        pthread_t clients[numClients];

        //Create Clients
        for(i=0; i< numClients; i++)
        {
            pthread_create(&clients[i], NULL, Lan, NULL);
        }

        //Join Clients
        for(i=0; i< numClients; i++)
        {
            pthread_join(clients[i], NULL);
        }

    }
    else
        printf("Please, insert a parameter.");
    pthread_exit(NULL);
    sem_destroy(&pc);
    return 0;
}
PlayHardGoPro
  • 2,791
  • 10
  • 51
  • 90

2 Answers2

1

If you're going to be technical, if you're syncing tasks between threads you should use Semaphore. Example reading input before parsing it. Here's an answer on semaphores.

But if you're using shared resources, and need to avoid race condition/two threads accesing at the same time, you should use mutexes. Here's a question on what is a mutex.

Also look at the disambiguation by Michael Barr which is a really good.

I would read both question thoroughly and the disambiguation, and you might actually end up not using semaphore and just mutexes since from what you explained you're only controlling a shared resource.

Common semaphore function

int sem_init(sem_t *sem, int pshared, unsigned int value); //Use pshared with 0, starts the semaphore with a given value

int sem_wait(sem_t *sem);//decreases the value of a semaphore, if it's in 0 it waits until it's increased

int sem_post(sem_t *sem);//increases the semaphore by 1

int sem_getvalue(sem_t *sem, int *valp);// returns in valp the value of the semaphore the returned int is error control

int sem_destroy(sem_t *sem);//destroys a semaphore created with sim_init

Common Mutexes functions (for linux not sure what O.S. you're running on)

int pthread_mutex_init(pthread_mutex_t *p_mutex, const pthread_mutexattr_t *attr); //starts mutex pointed by p_mutex, use attr NULL for simple use

int pthread_mutex_lock(pthread_mutex_t *p_mutex); //locks the mutex

int pthread_mutex_unlock(pthread_mutex_t *p_mutex); //unlocks the mutex

int pthread_mutex_destroy(pthread_mutex_t *p_mutex);//destroys the mutex
Community
  • 1
  • 1
Mr. Branch
  • 442
  • 2
  • 13
  • Will post edit with the common functions in both cases – Mr. Branch May 28 '16 at 02:38
  • I'm reading some answers of the topic you posted, I guess I should use semaphore anyway... Just don't get how to control the 'clients', 'computers' and 'queue'. Any tips ? – PlayHardGoPro May 28 '16 at 03:13
  • 1
    I'd use a queue data structure for the queue(this will be a little more complex), or maybe a circular buffer. If you know the max number of clients go for the buffer all the way. While you receive clients you place them in the queue/buffer, and when a computer frees up you assign the next client to the computer. If you're using semaphores when a client leaves sem_post, and have a handler check the value of the semaphores for each computer, as soon as one is >0 you assign a client to it. If you post some code I could help a little more. I'm just giving ideas so that you can try to start. – Mr. Branch May 28 '16 at 03:21
1

You can treat computers as resources. The data structure for the resource can be initialized by the main thread. Then, there can be client threads trying to acquire an instance of resource (a computer). You can use a counting semaphore with a value 3 for the number of computers. To acquire a computer, a client thread does

P (computer_sem).

Similarly to release the client thread has to do,

V (computer_sem)

For more information on threads and semaphore usage, refer POSIX Threads Synchronization in C.

kjohri
  • 1,166
  • 11
  • 10
  • But the resources (computer) can be anything ? Like vector with 3 positions and 0 or 1 (bussy or avaliable) ? Can't understand how I'll 'tell' which computer are been used by which client. – PlayHardGoPro May 28 '16 at 21:04
  • If you use a counting semaphore, the resources are assumed to be identical. If the resources are different, use one semaphore for each resource. – kjohri May 28 '16 at 23:05
  • Got ya ! Could you take a look in my code please... Just some guidance. Sometimes they only use the PC 0 and sometimes they use 0 and 1 but they leave 1 before enter it. Its a mess – PlayHardGoPro May 28 '16 at 23:08
  • I suggest that a good approach is to take a working example and model code around it. – kjohri May 29 '16 at 01:31