Solution for Python Unisex Bathroom Problem

Asked

Viewed 272 times

0

Suppose you are at a party in the Republic Calamity Public that has only one bathroom with n boxes, where box is a compartment with a toilet. The republic rule says that the bathroom can be used by both men and women, but not at the same time. Make a concurrent monitor-based algorithm that controls the usage of this bathroom.

The entrance to the bathroom is performed by the procedure inBanheiro. After entering the bathroom successfully, people should call the chosen procedure Ox, to use a box. If all the pits are in use then they should wait in a row as there is not enough room in the bathroom. After using a box, each person calls the liberatBox procedure so that others can use it.

The republic still imposes that the use of the bathroom should be fair as follows. Suppose, at a certain instant, the bathroom is in use by x people of the same sex (some using boxes and others waiting), and the first person of the opposite sex arrives, called P.

So:

• P only enters the bathroom after the exit of all x individuals from the bathroom;

• While P is waiting, if other individuals of the same sex arrive, they will use the bathroom simultaneously with P;

• While P is waiting, if individuals of the opposite sex arrive to use the bathroom, they enter the bathroom after P (and his same-sex companions, if any) leave the bathroom;

• While P (and same-sex companions) are using the bathroom, if same-sex P people arrive, they will expect all people of the opposite sex of P to leave before they start using the bathroom.

Each person of both sexes should be a separate process. There is no one controlling access to the bathroom, but all people know the rules of use of the bathroom and obey them (nobody sticks the queue!).

Three problems should be addressed:

Problem 1 Consider that the bathroom has only one box (n = 1). In all, 50 people will use the bathroom, with a random number generator defining gender (with equal probability). Use a random number generator so that the time between arrival of people is between 1 and 7 seconds. Each person uses the bathroom for exactly 5 seconds. Use threads and monitors for synchronization. You can also use shared memory.

At the end of the execution of the program a report containing:

• Number of persons of each sex;

• Average waiting time to use bathroom for each sex;

• Box occupancy rate (time in use / total time).

Problem 2: Consider now that the bathroom has 3 boxes (n = 3) and that the total number of people is 150.

Problem 3: Consider now that the bathroom has 5 boxes (n = 5) and that the total number of people is 250

import threading
import random
from time import sleep

# constants
MALE = 1
FEMALE = 0

print("\n***************************************************************\nBem vindo ao banheiro unisex da Rep. Calamidade Pública\n***************************************************************\n\nDigite 1 para Problema 1\nDigite 2 para Problema 2\nDigite 3 para Problema 3\n\n***************************************************************")
print("")
menu = input("Seleção: ")

# global variables
queue = list()               # to maintain queue outside bathroom
countPerson = 1                  # provides id for each person
countMale = 0
countFemale = 0
PeopleInBathroom = 0
GenderUsingBathroom = 0

if menu == '1':
    numBox = 1
elif menu == '2':
    numBox = 3
elif menu == '3':
    numBox = 5


# semaphores
sem_bathroom = threading.Semaphore(value=numBox)
sem_queue = threading.Semaphore()
sem_mutex = threading.Semaphore()


#generates people who need to use bathroom at random times
def GeneratePeople():
    global queue
    global countMale
    global countFemale
    global countPerson

    if menu == '1':
        sem_queue.acquire()
        for i in range(0, 50):
            if random.randint(0,1) == MALE:
                queue.insert(0,[MALE,countPerson]);
                countPerson += 1
                countMale += 1
                print ("Um homem chegou na fila na posição #", countPerson-1)
                sleep(random.randint(1, 7))
            else:
                queue.insert(0,[FEMALE,countPerson]);
                countPerson += 1
                countFemale += 1
                print ("Uma mulher chegou na fila na posição #", countPerson-1)
                sleep(random.randint(1, 7))
        sem_queue.release()
    elif menu == '2':
        sem_queue.acquire()
        for i in range(0, 150):
            if random.randint(0,1) == MALE:
                queue.insert(0,[MALE,countPerson]);
                countPerson += 1
                countMale += 1
                print ("Um homem chegou na fila na posição #", countPerson-1)
                sleep(random.randint(1, 7))
            else:
                queue.insert(0,[FEMALE,countPerson]);
                countPerson += 1
                countFemale += 1
                print ("Uma mulher chegou na fila na posição #", countPerson-1)
                sleep(random.randint(1, 7))
        sem_queue.release()
    elif menu == '3':
        sem_queue.acquire()
        for i in range(0, 250):
            if random.randint(0,1) == MALE:
                queue.insert(0,[MALE,countPerson]);
                countPerson += 1
                countMale += 1
                print ("Um homem chegou na fila na posição #", countPerson-1)
                sleep(random.randint(1, 7))
            else:
                queue.insert(0,[FEMALE,countPerson]);
                countPerson += 1
                countFemale += 1
                print ("Uma mulher chegou na fila na posição #", countPerson-1)
                sleep(random.randint(1, 7))
        sem_queue.release()
# end of GeneratePeople

# function to send people into bathroom for queue
def entraBanheiro():
    global queue
    global GenderUsingBathroom
    global PeopleInBathroom

    while 1:
        sem_queue.acquire()
        if len(queue)>0:
            p = queue.pop()
            sem_queue.release()
            sem_mutex.acquire()  # for GenderUsingBathroom
            if GenderUsingBathroom == p[0] :    # if same gender, go in
                sem_mutex.release()
                sem_bathroom.acquire()
                t = threading.Thread(target=liberaBox,args=(p,))
                t.start()
            else:                               # if different gender, wait till all others come out
                print ("Esperando por outra pessoa do mesmo sexo")
                while PeopleInBathroom > 0:
                    sem_mutex.release()
                    sleep(1)
                    sem_mutex.acquire()
                sem_mutex.release()
                sem_bathroom.acquire()
                GenderUsingBathroom = p[0]
                t1 = threading.Thread(target=liberaBox,args=(p,))
                t1.start()
        else:
            sem_queue.release()
# end of entraBanheiro


def liberaBox(person):             # monitors the usage of bathroom for each person
    global PeopleInBathroom
    flag = 1
    sem_mutex.acquire()
    if person[0] == FEMALE:
        print("Uma mulher acabou de entrar no banheiro")
        flag = 0
    else:
        print ("Um homem acabou de entrar no banheiro")
    PeopleInBathroom += 1   # enters bathroom
    sem_mutex.release()
    sleep(5)    # spend some time in bathroom
    sem_mutex.acquire()
    PeopleInBathroom -= 1   #leave bathroom
    print ("Pessoa #" , person[1]," acabou de sair do banheiro")
    sem_mutex.release()
    sem_bathroom.release()
# end of liberaBox

if __name__ == "__main__":

    t1 = threading.Thread(target=GeneratePeople)
    t1.start()
    t2 = threading.Thread(target=entraBanheiro)
    t2.start()

    #print("\n***************************************************************\nEstatisticas\n\n***************************************************************\n")
    #print("Homens: ", countMale)
    #print("Mulheres: ", countFemale)

The big problem is that it is not running the second thread, it first puts everyone in the bathroom queue then lets in.

1 answer

0


def GeneratePeople():
    global queue
    global countMale
    global countFemale
    global countPerson

    if menu == '1':
        sem_queue.acquire()
        for i in range(0, 50):
            if random.randint(0,1) == MALE:
                queue.put([MALE,countPerson]);
                countPerson += 1
                countMale += 1
                print ("Um homem chegou na fila na posição #", countPerson-1)
                sleep(random.randint(1, 7))
            else:
                queue.put([FEMALE,countPerson]);
                countPerson += 1
                countFemale += 1
                print ("Uma mulher chegou na fila na posição #", countPerson-1)
                sleep(random.randint(1, 7))
        sem_queue.release()
    elif menu == '2':
        sem_queue.acquire()
        for i in range(0, 150):
            if random.randint(0,1) == MALE:
                queue.put([MALE,countPerson]);
                countPerson += 1
                countMale += 1
                print ("Um homem chegou na fila na posição #", countPerson-1)
                sleep(random.randint(1, 7))
            else:
                queue.put([FEMALE,countPerson]);
                countPerson += 1
                countFemale += 1
                print ("Uma mulher chegou na fila na posição #", countPerson-1)
                sleep(random.randint(1, 7))
        sem_queue.release()
    elif menu == '3':
        sem_queue.acquire()
        for i in range(0, 250):
            if random.randint(0,1) == MALE:
                queue.put([MALE,countPerson]);
                countPerson += 1
                countMale += 1
                print ("Um homem chegou na fila na posição #", countPerson-1)
                sleep(random.randint(1, 7))
            else:
                queue.put([FEMALE,countPerson]);
                countPerson += 1
                countFemale += 1
                print ("Uma mulher chegou na fila na posição #", countPerson-1)
                sleep(random.randint(1, 7))
        sem_queue.release()

# end of GeneratePeople

# function to send people into bathroom for queue
def entraBanheiro():
    global queue
    global GenderUsingBathroom
    global PeopleInBathroom

    while 1:
        sem_queue.acquire()
        if queue.qsize() > 0:
            p = queue.get()
            sem_queue.release()
            sem_mutex.acquire()  # for GenderUsingBathroom
            if GenderUsingBathroom == p[0] :    # if same gender, go in
                sem_mutex.release()
                sem_bathroom.acquire()
                t1 = threading.Thread(target=liberaBox,args=(p,))
                t1.start()
            else:                               # if different gender, wait till all others come out
                print ("Esperando por outra pessoa do mesmo sexo")
                while PeopleInBathroom > 0:
                    sem_mutex.release()
                    #sleep(1)
                    sem_mutex.acquire()
                sem_mutex.release()
                sem_bathroom.acquire()
                GenderUsingBathroom = p[0]
                t2 = threading.Thread(target=liberaBox,args=(p,))
                t2.start()
        else:
            sem_queue.release()
# end of entraBanheiro


def liberaBox(person):             # monitors the usage of bathroom for each person
    global PeopleInBathroom
    flag = 1
    sem_mutex.acquire()
    if person[0] == FEMALE:
        print("Uma mulher acabou de entrar no banheiro")
        flag = 0
    else:
        print ("Um homem acabou de entrar no banheiro")
    PeopleInBathroom += 1   # enters bathroom
    sem_mutex.release()
    sleep(5)    # spend some time in bathroom
    sem_mutex.acquire()
    PeopleInBathroom -= 1   #leave bathroom
    print ("Pessoa #" , person[1]," acabou de sair do banheiro")
    sem_mutex.release()
    sem_bathroom.release()
# end of liberaBox

if __name__ == "__main__":

      t3 = Process(target=GeneratePeople).start()
      t4 = Process(target=entraBanheiro).start()

Browser other questions tagged

You are not signed in. Login or sign up in order to post.