Skip to content

Commit 1abc78d

Browse files
committed
added producer consumer semaphore solution
1 parent 4388fec commit 1abc78d

4 files changed

+362
-4
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@ py -3.11 -m pip install numpy
3030
[Python File](./same_python_file/mutex_lock.py)
3131

3232
### Lab - 3 == Semaphore Solution in Process-Synchronization (Producer Consumer Problem)
33-
[jupyter File](./unimodal_multimodal_density_curves_normal_distribution.ipynb) <br/>
34-
[Python File](./same_python_file/unimodal_multimodal_density_curves_normal_distribution.py)
33+
[jupyter File](./semaphore_producer_consumer.ipynb) <br/>
34+
[Python File](./same_python_file/semaphore_producer_consumer.py) &nbsp;&nbsp; / &nbsp;&nbsp; [Python File Alternative](./same_python_file/semaphore_producer_consumer_alternative.py)
3535

3636
### Lab - 4 == Semaphore Solution in Process-Synchronization (Dining Philosopher Problem)
3737
[jupyter File](./exponential_distribution.ipynb) <br/>
3838
[Python File](./same_python_file/exponential_distribution.py)
3939

4040
### Lab - 5 == Banker’s Algorithm (Deadlock Avoidance)
41-
[jupyter File](./inverse_exponential_distribution.ipynb) <br/>
42-
[Python File](./same_python_file/inverse_exponential_distribution.py)
41+
[jupyter File](./bankers_algorithm.ipynb) <br/>
42+
[Python File](./same_python_file/bankers_algorithm.py)
4343

4444
### Lab - 5 == Deadlock Detection
4545
[jupyter File](./inverse_exponential_distribution.ipynb) <br/>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import threading
2+
import time
3+
4+
mutex = threading.Semaphore(1)
5+
full = threading.Semaphore(0)
6+
empty = threading.Semaphore(3)
7+
x = 0
8+
9+
def producer():
10+
global mutex, full, empty, x
11+
empty.acquire()
12+
mutex.acquire()
13+
x += 1
14+
print(f"Producer produces item {x}\n")
15+
mutex.release()
16+
full.release()
17+
18+
def consumer():
19+
global mutex, full, empty, x
20+
full.acquire()
21+
mutex.acquire()
22+
print(f"Consumer consumes item {x}\n")
23+
x -= 1
24+
mutex.release()
25+
empty.release()
26+
27+
def main():
28+
while True:
29+
print("1. PRODUCER\n2. CONSUMER\n3. EXIT")
30+
n = int(input("ENTER YOUR CHOICE: \n"))
31+
if n == 1:
32+
if empty._value != 0:
33+
producer_thread = threading.Thread(target=producer)
34+
producer_thread.start()
35+
else:
36+
print("BUFFER IS FULL")
37+
elif n == 2:
38+
if full._value != 0:
39+
consumer_thread = threading.Thread(target=consumer)
40+
consumer_thread.start()
41+
else:
42+
print("BUFFER IS EMPTY")
43+
elif n == 3:
44+
break
45+
else:
46+
print("Invalid choice. Please try again.")
47+
48+
if __name__ == "__main__":
49+
main()
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import threading
2+
import time
3+
import random
4+
5+
# Buffer size
6+
BUFFER_SIZE = 5
7+
8+
# Semaphore to control access to the buffer
9+
mutex = threading.Semaphore(1)
10+
11+
# Semaphore to count the empty slots in the buffer
12+
empty = threading.Semaphore(BUFFER_SIZE)
13+
14+
# Semaphore to count the number of items in the buffer
15+
full = threading.Semaphore(0)
16+
17+
# Buffer to store items
18+
buffer = []
19+
20+
# The producer function, responsible for producing items
21+
def producer():
22+
for _ in range(10):
23+
# Generate a random item to be produced
24+
item = random.randint(1, 100)
25+
26+
# Acquire an empty slot in the buffer
27+
empty.acquire()
28+
29+
# Acquire the mutex to ensure mutual exclusion when accessing the buffer
30+
mutex.acquire()
31+
32+
# Add the item to the buffer
33+
buffer.append(item)
34+
35+
# Print a message indicating the item is produced and the current buffer contents
36+
print(f"Producer: Produced item {item}. Buffer: {buffer}")
37+
38+
# Release the mutex to allow other threads to access the buffer
39+
mutex.release()
40+
41+
# Release a full slot in the buffer to signal that an item is available
42+
full.release()
43+
44+
# Introduce a random delay to simulate variable production time
45+
time.sleep(random.uniform(0.1, 0.5))
46+
47+
# The consumer function, responsible for consuming items
48+
def consumer():
49+
for _ in range(10):
50+
# Acquire a full slot in the buffer to check if an item is available for consumption
51+
full.acquire()
52+
53+
# Acquire the mutex to ensure mutual exclusion when accessing the buffer
54+
mutex.acquire()
55+
56+
# Remove the first item from the buffer
57+
item = buffer.pop(0)
58+
59+
# Print a message indicating the item is consumed and the current buffer contents
60+
print(f"Consumer: Consumed item {item}. Buffer: {buffer}")
61+
62+
# Release the mutex to allow other threads to access the buffer
63+
mutex.release()
64+
65+
# Release an empty slot in the buffer to signal that a slot is available for production
66+
empty.release()
67+
68+
# Introduce a random delay to simulate variable consumption time
69+
time.sleep(random.uniform(0.1, 0.5))
70+
71+
if __name__ == "__main__":
72+
# Create producer and consumer threads
73+
producer_thread = threading.Thread(target=producer)
74+
consumer_thread = threading.Thread(target=consumer)
75+
76+
# Start the threads
77+
producer_thread.start()
78+
consumer_thread.start()
79+
80+
# Wait for the threads to complete
81+
producer_thread.join()
82+
consumer_thread.join()
83+
84+
# Print a message indicating that the simulation is completed
85+
print("Producer-Consumer simulation completed.")

semaphore_producer_consumer.ipynb

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": [
9+
"import threading\n",
10+
"import time\n",
11+
"\n",
12+
"# Declare three semaphore variables: mutex, full, and empty.\n",
13+
"# mutex is used to ensure mutual exclusion when accessing shared variables.\n",
14+
"# full represents the number of full slots in the buffer.\n",
15+
"# empty represents the number of empty slots in the buffer.\n",
16+
"mutex = threading.Semaphore(1)\n",
17+
"full = threading.Semaphore(0)\n",
18+
"empty = threading.Semaphore(3)\n",
19+
"\n",
20+
"# Variable to keep track of the item count.\n",
21+
"x = 0\n",
22+
"\n",
23+
"# The producer function, responsible for producing items.\n",
24+
"def producer():\n",
25+
" global mutex, full, empty, x\n",
26+
"\n",
27+
" # Acquire an empty slot in the buffer.\n",
28+
" empty.acquire()\n",
29+
"\n",
30+
" # Acquire the mutex to ensure mutual exclusion when accessing shared variables.\n",
31+
" mutex.acquire()\n",
32+
"\n",
33+
" # Increment the item count.\n",
34+
" x += 1\n",
35+
"\n",
36+
" # Print a message indicating the item is produced.\n",
37+
" print(f\"Producer produces item {x}\\n\")\n",
38+
"\n",
39+
" # Release the mutex to allow other threads to access shared variables.\n",
40+
" mutex.release()\n",
41+
"\n",
42+
" # Release a full slot in the buffer.\n",
43+
" full.release()\n",
44+
"\n",
45+
"# The consumer function, responsible for consuming items.\n",
46+
"def consumer():\n",
47+
" global mutex, full, empty, x\n",
48+
"\n",
49+
" # Acquire a full slot in the buffer.\n",
50+
" full.acquire()\n",
51+
"\n",
52+
" # Acquire the mutex to ensure mutual exclusion when accessing shared variables.\n",
53+
" mutex.acquire()\n",
54+
"\n",
55+
" # Print a message indicating the item is consumed.\n",
56+
" print(f\"Consumer consumes item {x}\\n\")\n",
57+
"\n",
58+
" # Decrement the item count.\n",
59+
" x -= 1\n",
60+
"\n",
61+
" # Release the mutex to allow other threads to access shared variables.\n",
62+
" mutex.release()\n",
63+
"\n",
64+
" # Release an empty slot in the buffer.\n",
65+
" empty.release()\n",
66+
"\n",
67+
"# The main function to start the producer-consumer simulation.\n",
68+
"def main():\n",
69+
" while True:\n",
70+
" # Display the menu for user selection.\n",
71+
" print(\"1. PRODUCER\\n2. CONSUMER\\n3. EXIT\")\n",
72+
" n = int(input(\"ENTER YOUR CHOICE: \\n\"))\n",
73+
"\n",
74+
" if n == 1:\n",
75+
" # If the buffer is not full, start a new producer thread.\n",
76+
" if empty._value != 0:\n",
77+
" producer_thread = threading.Thread(target=producer)\n",
78+
" producer_thread.start()\n",
79+
" else:\n",
80+
" print(\"BUFFER IS FULL\")\n",
81+
"\n",
82+
" elif n == 2:\n",
83+
" # If the buffer is not empty, start a new consumer thread.\n",
84+
" if full._value != 0:\n",
85+
" consumer_thread = threading.Thread(target=consumer)\n",
86+
" consumer_thread.start()\n",
87+
" else:\n",
88+
" print(\"BUFFER IS EMPTY\")\n",
89+
"\n",
90+
" elif n == 3:\n",
91+
" # Exit the program.\n",
92+
" break\n",
93+
"\n",
94+
" else:\n",
95+
" print(\"Invalid choice. Please try again.\")\n",
96+
"\n",
97+
"if __name__ == \"__main__\":\n",
98+
" main()\n"
99+
]
100+
},
101+
{
102+
"cell_type": "markdown",
103+
"metadata": {},
104+
"source": [
105+
"#### Altenative"
106+
]
107+
},
108+
{
109+
"cell_type": "code",
110+
"execution_count": null,
111+
"metadata": {},
112+
"outputs": [],
113+
"source": [
114+
"import threading\n",
115+
"import time\n",
116+
"import random\n",
117+
"\n",
118+
"# Buffer size\n",
119+
"BUFFER_SIZE = 5\n",
120+
"\n",
121+
"# Semaphore to control access to the buffer\n",
122+
"mutex = threading.Semaphore(1)\n",
123+
"\n",
124+
"# Semaphore to count the empty slots in the buffer\n",
125+
"empty = threading.Semaphore(BUFFER_SIZE)\n",
126+
"\n",
127+
"# Semaphore to count the number of items in the buffer\n",
128+
"full = threading.Semaphore(0)\n",
129+
"\n",
130+
"# Buffer to store items\n",
131+
"buffer = []\n",
132+
"\n",
133+
"# The producer function, responsible for producing items\n",
134+
"def producer():\n",
135+
" for _ in range(10):\n",
136+
" # Generate a random item to be produced\n",
137+
" item = random.randint(1, 100)\n",
138+
"\n",
139+
" # Acquire an empty slot in the buffer\n",
140+
" empty.acquire()\n",
141+
"\n",
142+
" # Acquire the mutex to ensure mutual exclusion when accessing the buffer\n",
143+
" mutex.acquire()\n",
144+
"\n",
145+
" # Add the item to the buffer\n",
146+
" buffer.append(item)\n",
147+
"\n",
148+
" # Print a message indicating the item is produced and the current buffer contents\n",
149+
" print(f\"Producer: Produced item {item}. Buffer: {buffer}\")\n",
150+
"\n",
151+
" # Release the mutex to allow other threads to access the buffer\n",
152+
" mutex.release()\n",
153+
"\n",
154+
" # Release a full slot in the buffer to signal that an item is available\n",
155+
" full.release()\n",
156+
"\n",
157+
" # Introduce a random delay to simulate variable production time\n",
158+
" time.sleep(random.uniform(0.1, 0.5))\n",
159+
"\n",
160+
"# The consumer function, responsible for consuming items\n",
161+
"def consumer():\n",
162+
" for _ in range(10):\n",
163+
" # Acquire a full slot in the buffer to check if an item is available for consumption\n",
164+
" full.acquire()\n",
165+
"\n",
166+
" # Acquire the mutex to ensure mutual exclusion when accessing the buffer\n",
167+
" mutex.acquire()\n",
168+
"\n",
169+
" # Remove the first item from the buffer\n",
170+
" item = buffer.pop(0)\n",
171+
"\n",
172+
" # Print a message indicating the item is consumed and the current buffer contents\n",
173+
" print(f\"Consumer: Consumed item {item}. Buffer: {buffer}\")\n",
174+
"\n",
175+
" # Release the mutex to allow other threads to access the buffer\n",
176+
" mutex.release()\n",
177+
"\n",
178+
" # Release an empty slot in the buffer to signal that a slot is available for production\n",
179+
" empty.release()\n",
180+
"\n",
181+
" # Introduce a random delay to simulate variable consumption time\n",
182+
" time.sleep(random.uniform(0.1, 0.5))\n",
183+
"\n",
184+
"if __name__ == \"__main__\":\n",
185+
" # Create producer and consumer threads\n",
186+
" producer_thread = threading.Thread(target=producer)\n",
187+
" consumer_thread = threading.Thread(target=consumer)\n",
188+
"\n",
189+
" # Start the threads\n",
190+
" producer_thread.start()\n",
191+
" consumer_thread.start()\n",
192+
"\n",
193+
" # Wait for the threads to complete\n",
194+
" producer_thread.join()\n",
195+
" consumer_thread.join()\n",
196+
"\n",
197+
" # Print a message indicating that the simulation is completed\n",
198+
" print(\"Producer-Consumer simulation completed.\")\n"
199+
]
200+
}
201+
],
202+
"metadata": {
203+
"kernelspec": {
204+
"display_name": "Python 3",
205+
"language": "python",
206+
"name": "python3"
207+
},
208+
"language_info": {
209+
"codemirror_mode": {
210+
"name": "ipython",
211+
"version": 3
212+
},
213+
"file_extension": ".py",
214+
"mimetype": "text/x-python",
215+
"name": "python",
216+
"nbconvert_exporter": "python",
217+
"pygments_lexer": "ipython3",
218+
"version": "3.11.0"
219+
},
220+
"orig_nbformat": 4
221+
},
222+
"nbformat": 4,
223+
"nbformat_minor": 2
224+
}

0 commit comments

Comments
 (0)