0

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

Entry into the bathroom is carried out by the procedure in the bathroom. After entering the bathroom successfully, people should call the procedureBoxBox, to use a box If all the boxes are in use then they should wait in a queue, there is enough space in the bathroom. After using a box, each person calls the procedure liberaBox so that others can use it.

The republic still imposes that the use of the bathroom should be fair as follows. Suppose that at one point the bathroom is in use by 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;

• As long as 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 to use the bathroom, they enter the bathroom after P (and their same-sex mates, if any) get out of the bathroom;

• While P (and same-sex mates) are using the bathroom, if same sex as P, they will expect all people of the opposite sex from P to leave before you 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 the line!).

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 setting the 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 sex;

• Average waiting time to use the 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 problem is the code generates all people first then they enter in WC. How to implement this for both thread run at same time?

matbrgz
  • 11
  • 4
  • 1
    Use multiprocessing instead of threading. Threads in python are not really parallel. Take a look at this: https://stackoverflow.com/questions/1697571/python-threading-appears-to-run-threads-sequentially This is what you are looking for: https://stackoverflow.com/questions/2046603/is-it-possible-to-run-function-in-a-subprocess-without-threading-or-writing-a-se – epinal Dec 05 '17 at 23:21
  • Not working, how to implement a process?? – matbrgz Dec 05 '17 at 23:33
  • https://stackoverflow.com/a/2046630/4585081 Make sure you change your queue to multiprocessing queue. Spam the 2 processes before calling join. – epinal Dec 05 '17 at 23:36
  • Nothing working, could you help me? – matbrgz Dec 06 '17 at 00:06
  • Already change the Queue, but what do you mean with Spam? @epinal – matbrgz Dec 06 '17 at 00:12
  • `p1 = Process(target=my_function1, args=(queue, 1))` `p2 = Process(target=my_function2, args=(queue, 2))` `p1.start()` `p2.start()` – epinal Dec 07 '17 at 01:10

1 Answers1

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()

But now my question is how to implement "Average waiting time to use the bathroom for each sex" and "Box occupancy rate (time in use / total time)"?

matbrgz
  • 11
  • 4