Solution to the Unisex Bathroom Problem in Python [closed]

1

Suppose you are at a party in the Public Calamity republic that has only one bathroom with n boxes, where box is a compartment with a toilet. The rule of the republic 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 use of this bathroom.

The entrance to the bathroom is carried out by the procedure entraBanheiro. After entering the bathroom successfully, people should call the procedure boxBox, to use a box. If all the boxes are in use then they should wait in a queue because there is not enough room in the bathroom. After using a box, each person calls the liberaBox procedure so that others can use it.

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

Then:

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

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

• While P is waiting, if individuals of the opposite sex come in to use the bathroom, they enter the bathroom after P (and their same-sex mates, if any) come out of the bathroom;

• While P (and same-sex partners) are using the bathroom, if people of the same sex as P come in, they will expect all people of the opposite sex to come out before they start using the bathroom. >

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

Three issues should be addressed:

Problem 1 Consider that the bathroom has only one box (n = 1). Altogether, 50 people will use the bathroom, with a random number generator defining sex (with equal probability). Use a random number generator so that the time between people arriving 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 program run a report containing:

• Number of people of each gender;

• Average wait time to use the bathroom for each sex;

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

Problem 2: Now consider 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 he is not running the second thread, he first puts everyone in the bathroom queue after he lets in.

    
asked by anonymous 06.12.2017 / 00:45

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()
    
06.12.2017 / 02:54