ಪೈಥಾನ್ ಮಲ್ಟಿಥ್ರೆಡಿಂಗ್: ಸಂದರ್ಶನ ಪ್ರಶ್ನೆಗಳು
1. ಮಲ್ಟಿಥ್ರೆಡಿಂಗ್ (Multithreading) ಎಂದರೇನು?
ಉತ್ತರ: ಮಲ್ಟಿಥ್ರೆಡಿಂಗ್ ಎನ್ನುವುದು ಒಂದೇ ಪ್ರೊಸೆಸ್ನೊಳಗೆ ಹಲವಾರು ಥ್ರೆಡ್ಗಳನ್ನು (ಸಣ್ಣ ಎಕ್ಸಿಕ್ಯೂಶನ್ ಯೂನಿಟ್ಗಳು) ಏಕಕಾಲದಲ್ಲಿ ( concurrently) ರನ್ ಮಾಡುವ ಪ್ರಕ್ರಿಯೆ. ಪ್ರತಿಯೊಂದು ಥ್ರೆಡ್ ತನ್ನದೇ ಆದ ಎಕ್ಸಿಕ್ಯೂಶನ್ ಸ್ಟಾಕ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ, ಆದರೆ ಅವು ಪ್ರೊಸೆಸ್ನ ಮೆಮೊರಿ ಮತ್ತು ರಿಸೋರ್ಸ್ಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತವೆ.
ಉಪಯೋಗ:
- I/O-ಬೌಂಡ್ ಟಾಸ್ಕ್ಗಳಿಗೆ: ನೆಟ್ವರ್ಕ್ ರಿಕ್ವೆಸ್ಟ್ಗಳು, ಫೈಲ್ ಆಪರೇಷನ್ಗಳಂತಹ ಸಮಯ ತೆಗೆದುಕೊಳ್ಳುವ I/O ಆಪರೇಷನ್ಗಳಿಗಾಗಿ ಕಾಯುತ್ತಿರುವಾಗ, ಬೇರೆ ಥ್ರೆಡ್ಗಳು ತಮ್ಮ ಕೆಲಸವನ್ನು ಮುಂದುವರಿಸಬಹುದು. ಇದು ಅಪ್ಲಿಕೇಶನ್ನ ರೆಸ್ಪಾನ್ಸಿವ್ನೆಸ್ ಅನ್ನು ಸುಧಾರಿಸುತ್ತದೆ.
2. ಪ್ರೊಸೆಸ್ (Process) ಮತ್ತು ಥ್ರೆಡ್ (Thread) ನಡುವಿನ ವ್ಯತ್ಯಾಸವೇನು?
ಉತ್ತರ:
| ಲಕ್ಷಣ | ಪ್ರೊಸೆಸ್ (Process) | ಥ್ರೆಡ್ (Thread) |
|---|---|---|
| ವ್ಯಾಖ್ಯಾನ | ಪ್ರೋಗ್ರಾಂನ ಒಂದು ರನ್ನಿಂಗ್ ಇನ್ಸ್ಟೆನ್ಸ್. | ಪ್ರೊಸೆಸ್ನೊಳಗಿನ ಒಂದು ಸಣ್ಣ ಎಕ್ಸಿಕ್ಯೂಶನ್ ಯೂನಿಟ್. |
| ಮೆಮೊರಿ | ಪ್ರತಿ ಪ್ರೊಸೆಸ್ಗೆ ತನ್ನದೇ ಆದ ಪ್ರತ್ಯೇಕ ಮೆಮೊರಿ ಸ್ಪೇಸ್ ಇರುತ್ತದೆ. | ಒಂದೇ ಪ್ರೊಸೆಸ್ನ ಎಲ್ಲಾ ಥ್ರೆಡ್ಗಳು |
| ಮೆಮೊರಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತವೆ. | ||
| ರಚನೆ | ಪ್ರೊಸೆಸ್ ರಚಿಸಲು ಹೆಚ್ಚು ಸಮಯ ಮತ್ತು ರಿಸೋರ್ಸ್ ಬೇಕು. | ಥ್ರೆಡ್ ರಚಿಸಲು ಕಡಿಮೆ ಸಮಯ ಮತ್ತು ರಿಸೋರ್ಸ್ ಬೇಕು. |
| ಸಂವಹನ | ಪ್ರೊಸೆಸ್ಗಳ ನಡುವಿನ ಸಂವಹನ (IPC) ಕಷ್ಟ ಮತ್ತು ನಿಧಾನ. | ಥ್ರೆಡ್ಗಳ ನಡುವಿನ ಸಂವಹನ ಸುಲಭ ಮತ್ತು ವೇಗ, ಏಕೆಂದರೆ ಅವು |
| ಮೆಮೊರಿ ಹಂಚಿಕೊಳ್ಳುತ್ತವೆ. | ||
| ದೋಷ | ಒಂದು ಪ್ರೊಸೆಸ್ ಕ್ರ್ಯಾಶ್ ಆದರೆ, ಬೇರೆ ಪ್ರೊಸೆಸ್ಗಳ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರುವುದಿಲ್ಲ. | ಒಂದು ಥ್ರೆಡ್ ಕ್ರ್ಯಾಶ್ ಆದರೆ, ಸಂಪೂರ್ಣ |
| ಪ್ರೊಸೆಸ್ ಕ್ರ್ಯಾಶ್ ಆಗಬಹುದು. |
3. GIL (Global Interpreter Lock) ಎಂದರೇನು?
ಉತ್ತರ: GIL ಎನ್ನುವುದು CPython (ಪೈಥಾನ್ನ ಡೀಫಾಲ್ಟ್ ಇಂಪ್ಲಿಮೆಂಟೇಶನ್) ನಲ್ಲಿರುವ ಒಂದು ಮ್ಯೂಟೆಕ್ಸ್ (mutex). ಇದು ಒಂದು ಸಮಯದಲ್ಲಿ ಒಂದೇ ಒಂದು ಥ್ರೆಡ್ ಮಾತ್ರ ಪೈಥಾನ್ ಬೈಟ್ಕೋಡ್ ಅನ್ನು ಎಕ್ಸಿಕ್ಯೂಟ್ ಮಾಡುವಂತೆ ಖಚಿತಪಡಿಸುತ್ತದೆ.
ಪರಿಣಾಮ:
- CPU-ಬೌಂಡ್ ಟಾಸ್ಕ್ಗಳಿಗೆ: ಗಣಿತದ ಲೆಕ್ಕಾಚಾರಗಳಂತಹ CPU-ತೀವ್ರವಾದ ಕೆಲಸಗಳಲ್ಲಿ, GIL ನಿಂದಾಗಿ ಮಲ್ಟಿಥ್ರೆಡಿಂಗ್ ನಿಜವಾದ ಪ್ಯಾರಲಲಿಸಂ ಅನ್ನು ನೀಡುವುದಿಲ್ಲ. ಇದರಿಂದಾಗಿ, ಮಲ್ಟಿಥ್ರೆಡಿಂಗ್ ಪ್ರೋಗ್ರಾಂ ಸಿಂಗಲ್-ಥ್ರೆಡೆಡ್ ಪ್ರೋಗ್ರಾಂ ಗಿಂತ ನಿಧಾನವಾಗಿರಬಹುದು.
- I/O-ಬೌಂಡ್ ಟಾಸ್ಕ್ಗಳಿಗೆ: ಒಂದು ಥ್ರೆಡ್ I/O ಗಾಗಿ ಕಾಯುತ್ತಿರುವಾಗ, GIL ಅನ್ನು ಬಿಡುಗಡೆ ಮಾಡುತ್ತದೆ, ಇದರಿಂದ ಬೇರೆ ಥ್ರೆಡ್ ರನ್ ಆಗಬಹುದು. ಆದ್ದರಿಂದ, I/O-ಬೌಂಡ್ ಟಾಸ್ಕ್ಗಳಿಗೆ ಮಲ್ಟಿಥ್ರೆಡಿಂಗ್ ಪರಿಣಾಮಕಾರಿಯಾಗಿದೆ.
4. ರೇಸ್ ಕಂಡೀಶನ್ (Race Condition) ಎಂದರೇನು? ಇದನ್ನು ಹೇಗೆ ತಡೆಯುವುದು?
ಉತ್ತರ: ರೇಸ್ ಕಂಡೀಶನ್ ಎನ್ನುವುದು ಹಲವಾರು ಥ್ರೆಡ್ಗಳು ಒಂದೇ ಶೇರ್ಡ್ ರಿಸೋರ್ಸ್ ಅನ್ನು (ಉದಾ: ವೇರಿಯೇಬಲ್) ಏಕಕಾಲದಲ್ಲಿ ಆಕ್ಸೆಸ್ ಮಾಡಲು ಮತ್ತು ಬದಲಾಯಿಸಲು ಪ್ರಯತ್ನಿಸಿದಾಗ ಸಂಭವಿಸುವ ಒಂದು ದೋಷ. ಎಕ್ಸಿಕ್ಯೂಶನ್ನ ಅಂತಿಮ ಫಲಿತಾಂಶವು ಥ್ರೆಡ್ಗಳು ಯಾವ ಕ್ರಮದಲ್ಲಿ ರನ್ ಆಗುತ್ತವೆ ಎಂಬುದರ ಮೇಲೆ ಅವಲಂಬಿತವಾಗಿರುತ್ತದೆ, ಇದು ಅನಿರೀಕ್ಷಿತ ಫಲಿತಾಂಶಗಳಿಗೆ ಕಾರಣವಾಗುತ್ತದೆ.
ತಡೆಯುವ ವಿಧಾನ (ಸಿಂಕ್ರೊನೈಸೇಶನ್):
threading ಮಾಡ್ಯೂಲ್ನಲ್ಲಿರುವ ಲಾಕ್ಸ್ (Locks) ಬಳಸಿ ರೇಸ್ ಕಂಡೀಶನ್ಗಳನ್ನು ತಡೆಯಬಹುದು.
- ಲಾಕ್ (Lock): ಒಂದು ಸಮಯದಲ್ಲಿ ಒಂದೇ ಒಂದು ಥ್ರೆಡ್ ಮಾತ್ರ ಕೋಡ್ನ ನಿರ್ಣಾಯಕ ಭಾಗವನ್ನು (critical section) ಪ್ರವೇಶಿಸುವಂತೆ ಲಾಕ್ ಖಚಿತಪಡಿಸುತ್ತದೆ.
acquire(): ಲಾಕ್ ಅನ್ನು ಪಡೆಯಲು ಪ್ರಯತ್ನಿಸುತ್ತದೆ. ಲಾಕ್ ಲಭ್ಯವಿದ್ದರೆ, ಥ್ರೆಡ್ ಮುಂದುವರಿಯುತ್ತದೆ. ಇಲ್ಲದಿದ್ದರೆ, ಲಾಕ್ ಬಿಡುಗಡೆಯಾಗುವವರೆಗೆ ಕಾಯುತ್ತದೆ.release(): ಲಾಕ್ ಅನ್ನು ಬಿಡುಗಡೆ ಮಾಡುತ್ತದೆ, ಇದರಿಂದ ಬೇರೆ ಥ್ರೆಡ್ ಅದನ್ನು ಪಡೆಯಬಹುದು.
ಉದಾಹರಣೆ:
import threading
balance = 0
lock = threading.Lock()
def deposit(amount):
global balance
for _ in range(100000):
lock.acquire()
balance += amount
lock.release()
t1 = threading.Thread(target=deposit, args=(1,))
t2 = threading.Thread(target=deposit, args=(1,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance) # ಲಾಕ್ ಇಲ್ಲದಿದ್ದರೆ, ಫಲಿತಾಂಶ 200000 ಕ್ಕಿಂತ ಕಡಿಮೆ ಇರಬಹುದು
5. ಡೆಡ್ಲಾಕ್ (Deadlock) ಎಂದರೇನು?
ಉತ್ತರ: ಡೆಡ್ಲಾಕ್ ಎನ್ನುವುದು ಎರಡು ಅಥವಾ ಅದಕ್ಕಿಂತ ಹೆಚ್ಚು ಥ್ರೆಡ್ಗಳು ಪರಸ್ಪರ ಹಿಡಿದಿಟ್ಟುಕೊಂಡಿರುವ ರಿಸೋರ್ಸ್ಗಳಿಗಾಗಿ ಕಾಯುತ್ತಾ, ಶಾಶ್ವತವಾಗಿ ಬ್ಲಾಕ್ ಆಗುವ ಒಂದು ಸ್ಥಿತಿ.
ಉದಾಹರಣೆ:
- ಥ್ರೆಡ್ A, ರಿಸೋರ್ಸ್ 1 ಅನ್ನು ಲಾಕ್ ಮಾಡಿ, ರಿಸೋರ್ಸ್ 2 ಕ್ಕಾಗಿ ಕಾಯುತ್ತಿದೆ.
- ಥ್ರೆಡ್ B, ರಿಸೋರ್ಸ್ 2 ಅನ್ನು ಲಾಕ್ ಮಾಡಿ, ರಿಸೋರ್ಸ್ 1 ಕ್ಕಾಗಿ ಕಾಯುತ್ತಿದೆ.
ಈ ಸ್ಥಿತಿಯಲ್ಲಿ, ಎರಡೂ ಥ್ರೆಡ್ಗಳು ಮುಂದುವರಿಯಲು ಸಾಧ್ಯವಿಲ್ಲ. ಡೆಡ್ಲಾಕ್ಗಳನ್ನು ತಪ್ಪಿಸಲು ಲಾಕಿಂಗ್ ಕ್ರಮವನ್ನು ಎಚ್ಚರಿಕೆಯಿಂದ ವಿನ್ಯಾಸಗೊಳಿಸಬೇಕು (ಉದಾ: ಎಲ್ಲಾ ಥ್ರೆಡ್ಗಳು ಒಂದೇ ಕ್ರಮದಲ್ಲಿ ಲಾಕ್ಗಳನ್ನು ಪಡೆಯುವುದು).