ಜಾಗತಿಕ ಡೆವಲಪರ್ಗಳಿಗಾಗಿ ಸಮಕಾಲೀನತೆ ನಿಯಂತ್ರಣದ ಕುರಿತು ಸಮಗ್ರ ಮಾರ್ಗದರ್ಶಿ. ಲಾಕ್-ಆಧಾರಿತ ಸಿಂಕ್ರೊನೈಸೇಶನ್, ಮ್ಯೂಟೆಕ್ಸ್ಗಳು, ಸೆಮಾಫೋರ್ಗಳು, ಡೆಡ್ಲಾಕ್ಗಳು ಮತ್ತು ಉತ್ತಮ ಅಭ್ಯಾಸಗಳನ್ನು ಅನ್ವೇಷಿಸಿ.
ಸಮಕಾಲೀನತೆಯಲ್ಲಿ ಪ್ರಾವೀಣ್ಯತೆ: ಲಾಕ್-ಆಧಾರಿತ ಸಿಂಕ್ರೊನೈಸೇಶನ್ ಕುರಿತು ಒಂದು ಆಳವಾದ ನೋಟ
ಒಂದು ಗಿಜಿಗುಡುವ ವೃತ್ತಿಪರ ಅಡುಗೆಮನೆಯನ್ನು ಕಲ್ಪಿಸಿಕೊಳ್ಳಿ. ಅನೇಕ ಬಾಣಸಿಗರು ಏಕಕಾಲದಲ್ಲಿ ಕೆಲಸ ಮಾಡುತ್ತಿದ್ದಾರೆ, ಅವರೆಲ್ಲರಿಗೂ ಪದಾರ್ಥಗಳಿರುವ ಹಂಚಿಕೆಯ ಉಗ್ರಾಣದ ಪ್ರವೇಶದ ಅಗತ್ಯವಿದೆ. ಒಂದೇ ಕ್ಷಣದಲ್ಲಿ ಇಬ್ಬರು ಬಾಣಸಿಗರು ಅಪರೂಪದ ಮಸಾಲೆಯ ಕೊನೆಯ ಜಾರ್ ಅನ್ನು ತೆಗೆದುಕೊಳ್ಳಲು ಪ್ರಯತ್ನಿಸಿದರೆ, ಅದು ಯಾರಿಗೆ ಸಿಗುತ್ತದೆ? ಒಬ್ಬ ಬಾಣಸಿಗ ರೆಸಿಪಿ ಕಾರ್ಡ್ ಅನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡುತ್ತಿರುವಾಗ ಇನ್ನೊಬ್ಬರು ಅದನ್ನು ಓದುತ್ತಿದ್ದರೆ, ಅದು ಅರ್ಧಂಬರ್ಧ ಬರೆದ, ಅಸಂಬದ್ಧ ಸೂಚನೆಗೆ ಕಾರಣವಾದರೆ ಏನು ಮಾಡುವುದು? ಅಡುಗೆಮನೆಯ ಈ ಗೊಂದಲವು ಆಧುನಿಕ ಸಾಫ್ಟ್ವೇರ್ ಅಭಿವೃದ್ಧಿಯಲ್ಲಿನ ಕೇಂದ್ರ ಸವಾಲಿಗೆ ಒಂದು ಪರಿಪೂರ್ಣ ಸಾದೃಶ್ಯವಾಗಿದೆ: ಸಮಕಾಲೀನತೆ (concurrency).
ಇಂದಿನ ಮಲ್ಟಿ-ಕೋರ್ ಪ್ರೊಸೆಸರ್ಗಳು, ವಿತರಿಸಿದ ವ್ಯವಸ್ಥೆಗಳು, ಮತ್ತು ಹೆಚ್ಚು ಸ್ಪಂದನಾಶೀಲ ಅಪ್ಲಿಕೇಶನ್ಗಳ ಜಗತ್ತಿನಲ್ಲಿ, ಸಮಕಾಲೀನತೆ—ಒಂದು ಪ್ರೋಗ್ರಾಂನ ವಿವಿಧ ಭಾಗಗಳು ಅಂತಿಮ ಫಲಿತಾಂಶದ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರದಂತೆ ಕ್ರಮಬಾಹಿರವಾಗಿ ಅಥವಾ ಭಾಗಶಃ ಕ್ರಮದಲ್ಲಿ ಕಾರ್ಯಗತಗೊಳ್ಳುವ ಸಾಮರ್ಥ್ಯ—ಒಂದು ಐಷಾರಾಮವಲ್ಲ; ಅದೊಂದು ಅವಶ್ಯಕತೆ. ವೇಗದ ವೆಬ್ ಸರ್ವರ್ಗಳು, ಸುಗಮ ಬಳಕೆದಾರ ಇಂಟರ್ಫೇಸ್ಗಳು, ಮತ್ತು ಶಕ್ತಿಯುತ ಡೇಟಾ ಸಂಸ್ಕರಣಾ ಪೈಪ್ಲೈನ್ಗಳ ಹಿಂದಿನ ಇಂಜಿನ್ ಇದೇ ಆಗಿದೆ. ಆದಾಗ್ಯೂ, ಈ ಶಕ್ತಿಯು ಗಣನೀಯ ಸಂಕೀರ್ಣತೆಯೊಂದಿಗೆ ಬರುತ್ತದೆ. ಯಾವಾಗ ಅನೇಕ ಥ್ರೆಡ್ಗಳು ಅಥವಾ ಪ್ರೊಸೆಸ್ಗಳು ಹಂಚಿಕೆಯ ಸಂಪನ್ಮೂಲಗಳನ್ನು ಏಕಕಾಲದಲ್ಲಿ ಪ್ರವೇಶಿಸುತ್ತವೆಯೋ, ಅವು ಪರಸ್ಪರ ಹಸ್ತಕ್ಷೇಪ ಮಾಡಬಹುದು, ಇದು ದೋಷಪೂರಿತ ಡೇಟಾ, ಅನಿರೀಕ್ಷಿತ ವರ್ತನೆ, ಮತ್ತು ಗಂಭೀರ ಸಿಸ್ಟಮ್ ವೈಫಲ್ಯಗಳಿಗೆ ಕಾರಣವಾಗುತ್ತದೆ. ಇಲ್ಲೇ ಸಮಕಾಲೀನತೆ ನಿಯಂತ್ರಣ (concurrency control) ಕಾರ್ಯರೂಪಕ್ಕೆ ಬರುತ್ತದೆ.
ಈ ಸಮಗ್ರ ಮಾರ್ಗದರ್ಶಿಯು ಈ ನಿಯಂತ್ರಿತ ಗೊಂದಲವನ್ನು ನಿರ್ವಹಿಸಲು ಅತ್ಯಂತ ಮೂಲಭೂತ ಮತ್ತು ವ್ಯಾಪಕವಾಗಿ ಬಳಸಲಾಗುವ ತಂತ್ರವನ್ನು ಅನ್ವೇಷಿಸುತ್ತದೆ: ಲಾಕ್-ಆಧಾರಿತ ಸಿಂಕ್ರೊನೈಸೇಶನ್ (lock-based synchronization). ನಾವು ಲಾಕ್ಗಳು ಎಂದರೇನು ಎಂಬುದನ್ನು ಸ್ಪಷ್ಟಪಡಿಸುತ್ತೇವೆ, ಅವುಗಳ ವಿವಿಧ ರೂಪಗಳನ್ನು ಅನ್ವೇಷಿಸುತ್ತೇವೆ, ಅವುಗಳ ಅಪಾಯಕಾರಿ ಮೋಸಗಳನ್ನು ನಿಭಾಯಿಸುತ್ತೇವೆ, ಮತ್ತು ದೃಢವಾದ, ಸುರಕ್ಷಿತ, ಮತ್ತು ಸಮರ್ಥವಾದ ಸಮಕಾಲೀನ ಕೋಡ್ ಬರೆಯಲು ಜಾಗತಿಕ ಉತ್ತಮ ಅಭ್ಯಾಸಗಳ ಗುಂಪನ್ನು ಸ್ಥಾಪಿಸುತ್ತೇವೆ.
ಸಮಕಾಲೀನತೆ ನಿಯಂತ್ರಣ ಎಂದರೇನು?
ಮೂಲಭೂತವಾಗಿ, ಸಮಕಾಲೀನತೆ ನಿಯಂತ್ರಣವು ಕಂಪ್ಯೂಟರ್ ವಿಜ್ಞಾನದ ಒಂದು ವಿಭಾಗವಾಗಿದ್ದು, ಹಂಚಿಕೆಯ ಡೇಟಾದ ಮೇಲೆ ಏಕಕಾಲೀನ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಮೀಸಲಾಗಿದೆ. ಇದರ ಪ್ರಾಥಮಿಕ ಗುರಿ ಏಕಕಾಲೀನ ಕಾರ್ಯಾಚರಣೆಗಳು ಪರಸ್ಪರ ಹಸ್ತಕ್ಷೇಪ ಮಾಡದೆ ಸರಿಯಾಗಿ ಕಾರ್ಯಗತಗೊಳ್ಳುವುದನ್ನು ಖಚಿತಪಡಿಸುವುದು, ಡೇಟಾ ಸಮಗ್ರತೆ ಮತ್ತು ಸ್ಥಿರತೆಯನ್ನು ಕಾಪಾಡುವುದು. ಇದನ್ನು ಅಡುಗೆಮನೆಯ ವ್ಯವಸ್ಥಾಪಕನಂತೆ ಯೋಚಿಸಿ, ಅವರು ಬಾಣಸಿಗರು ಪದಾರ್ಥಗಳ ಚೆಲ್ಲುವಿಕೆ, ಮಿಶ್ರಣ ಮತ್ತು ವ್ಯರ್ಥವಾಗುವುದನ್ನು ತಡೆಯಲು ಉಗ್ರಾಣವನ್ನು ಹೇಗೆ ಪ್ರವೇಶಿಸಬೇಕು ಎಂಬುದರ ಕುರಿತು ನಿಯಮಗಳನ್ನು ರೂಪಿಸುತ್ತಾರೆ.
ಡೇಟಾಬೇಸ್ಗಳ ಜಗತ್ತಿನಲ್ಲಿ, ACID ಗುಣಲಕ್ಷಣಗಳನ್ನು (ಅಟಾಮಿಸಿಟಿ, ಕನ್ಸಿಸ್ಟೆನ್ಸಿ, ಐಸೋಲೇಶನ್, ಡ್ಯೂರಬಿಲಿಟಿ), ವಿಶೇಷವಾಗಿ ಐಸೋಲೇಶನ್ (Isolation) ಅನ್ನು ನಿರ್ವಹಿಸಲು ಸಮಕಾಲೀನತೆ ನಿಯಂತ್ರಣ ಅತ್ಯಗತ್ಯ. ಟ್ರಾನ್ಸಾಕ್ಷನ್ಗಳನ್ನು ಒಂದರ ನಂತರ ಒಂದರಂತೆ ಸರಣೀಯವಾಗಿ ಕಾರ್ಯಗತಗೊಳಿಸಿದರೆ ಪಡೆಯಬಹುದಾದ ಸಿಸ್ಟಮ್ ಸ್ಥಿತಿಯು, ಸಮಕಾಲೀನ ಟ್ರಾನ್ಸಾಕ್ಷನ್ಗಳ ಕಾರ್ಯಗತಗೊಳಿಸುವಿಕೆಯಿಂದಲೂ ಉಂಟಾಗುತ್ತದೆ ಎಂಬುದನ್ನು ಐಸೋಲೇಶನ್ ಖಚಿತಪಡಿಸುತ್ತದೆ.
ಸಮಕಾಲೀನತೆ ನಿಯಂತ್ರಣವನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲು ಎರಡು ಪ್ರಾಥಮಿಕ ತತ್ವಗಳಿವೆ:
- ಆಪ್ಟಿಮಿಸ್ಟಿಕ್ (ಆಶಾವಾದಿ) ಸಮಕಾಲೀನತೆ ನಿಯಂತ್ರಣ: ಈ ವಿಧಾನವು ಸಂಘರ್ಷಗಳು ಅಪರೂಪವೆಂದು ಊಹಿಸುತ್ತದೆ. ಇದು ಯಾವುದೇ ಮುಂಗಡ ಪರಿಶೀಲನೆಗಳಿಲ್ಲದೆ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಮುಂದುವರಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ಬದಲಾವಣೆಯನ್ನು ಕಮಿಟ್ ಮಾಡುವ ಮೊದಲು, ಬೇರೆ ಕಾರ್ಯಾಚರಣೆಯು ಈ ಮಧ್ಯೆ ಡೇಟಾವನ್ನು ಮಾರ್ಪಡಿಸಿದೆಯೇ ಎಂದು ಸಿಸ್ಟಮ್ ಪರಿಶೀಲಿಸುತ್ತದೆ. ಸಂಘರ್ಷ ಪತ್ತೆಯಾದರೆ, ಕಾರ್ಯಾಚರಣೆಯನ್ನು ಸಾಮಾನ್ಯವಾಗಿ ಹಿಂತೆಗೆದುಕೊಳ್ಳಲಾಗುತ್ತದೆ ಮತ್ತು ಮರುಪ್ರಯತ್ನಿಸಲಾಗುತ್ತದೆ. ಇದು "ಅನುಮತಿ ಕೇಳುವುದಕ್ಕಿಂತ ಕ್ಷಮೆ ಕೇಳುವುದು ಉತ್ತಮ" ಎಂಬ ತಂತ್ರವಾಗಿದೆ.
- ಪೆಸ್ಸಿಮಿಸ್ಟಿಕ್ (ನಿರಾಶಾವಾದಿ) ಸಮಕಾಲೀನತೆ ನಿಯಂತ್ರಣ: ಈ ವಿಧಾನವು ಸಂಘರ್ಷಗಳು ಹೆಚ್ಚಾಗಿ ಸಂಭವಿಸುತ್ತವೆ ಎಂದು ಊಹಿಸುತ್ತದೆ. ಇದು ಒಂದು ಕಾರ್ಯಾಚರಣೆಯು ಸಂಪನ್ಮೂಲವನ್ನು ಪ್ರವೇಶಿಸುವ ಮೊದಲು ಅದರ ಮೇಲೆ ಲಾಕ್ ಪಡೆಯುವಂತೆ ಒತ್ತಾಯಿಸುತ್ತದೆ, ಇತರ ಕಾರ್ಯಾಚರಣೆಗಳು ಹಸ್ತಕ್ಷೇಪ ಮಾಡುವುದನ್ನು ತಡೆಯುತ್ತದೆ. ಇದು "ಕ್ಷಮೆ ಕೇಳುವುದಕ್ಕಿಂತ ಅನುಮತಿ ಕೇಳುವುದು ಉತ್ತಮ" ಎಂಬ ತಂತ್ರವಾಗಿದೆ.
ಈ ಲೇಖನವು ಸಂಪೂರ್ಣವಾಗಿ ನಿರಾಶಾವಾದಿ ವಿಧಾನದ ಮೇಲೆ ಕೇಂದ್ರೀಕರಿಸುತ್ತದೆ, ಇದು ಲಾಕ್-ಆಧಾರಿತ ಸಿಂಕ್ರೊನೈಸೇಶನ್ನ ಅಡಿಪಾಯವಾಗಿದೆ.
ಕೇಂದ್ರ ಸಮಸ್ಯೆ: ರೇಸ್ ಕಂಡೀಶನ್ಗಳು
ನಾವು ಪರಿಹಾರವನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವ ಮೊದಲು, ನಾವು ಸಮಸ್ಯೆಯನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ಅರ್ಥಮಾಡಿಕೊಳ್ಳಬೇಕು. ಸಮಕಾಲೀನ ಪ್ರೋಗ್ರಾಮಿಂಗ್ನಲ್ಲಿ ಅತ್ಯಂತ ಸಾಮಾನ್ಯ ಮತ್ತು ವಂಚಕ ದೋಷವೆಂದರೆ ರೇಸ್ ಕಂಡೀಶನ್ (race condition). ಆಪರೇಟಿಂಗ್ ಸಿಸ್ಟಮ್ನಿಂದ ಥ್ರೆಡ್ಗಳ ಶೆಡ್ಯೂಲಿಂಗ್ನಂತಹ ಅನಿಯಂತ್ರಿತ ಘಟನೆಗಳ ಅನಿರೀಕ್ಷಿತ ಅನುಕ್ರಮ ಅಥವಾ ಸಮಯದ ಮೇಲೆ ಸಿಸ್ಟಮ್ನ ನಡವಳಿಕೆಯು ಅವಲಂಬಿತವಾದಾಗ ರೇಸ್ ಕಂಡೀಶನ್ ಸಂಭವಿಸುತ್ತದೆ.
ಒಂದು ಹಂಚಿಕೆಯ ಬ್ಯಾಂಕ್ ಖಾತೆಯ ಶ್ರೇಷ್ಠ ಉದಾಹರಣೆಯನ್ನು ಪರಿಗಣಿಸೋಣ. ಒಂದು ಖಾತೆಯಲ್ಲಿ $1000 ಬ್ಯಾಲೆನ್ಸ್ ಇದೆ ಎಂದು ಭಾವಿಸೋಣ, ಮತ್ತು ಎರಡು ಸಮಕಾಲೀನ ಥ್ರೆಡ್ಗಳು ತಲಾ $100 ಠೇವಣಿ ಮಾಡಲು ಪ್ರಯತ್ನಿಸುತ್ತವೆ.
ಠೇವಣಿಗಾಗಿ ಕಾರ್ಯಾಚರಣೆಗಳ ಸರಳೀಕೃತ ಅನುಕ್ರಮ ಇಲ್ಲಿದೆ:
- ಮೆಮೊರಿಯಿಂದ ಪ್ರಸ್ತುತ ಬ್ಯಾಲೆನ್ಸ್ ಓದಿ.
- ಈ ಮೌಲ್ಯಕ್ಕೆ ಠೇವಣಿ ಮೊತ್ತವನ್ನು ಸೇರಿಸಿ.
- ಹೊಸ ಮೌಲ್ಯವನ್ನು ಮೆಮೊರಿಗೆ ಮತ್ತೆ ಬರೆಯಿರಿ.
ಸರಿಯಾದ, ಸರಣೀಯ ಕಾರ್ಯಗತಗೊಳಿಸುವಿಕೆಯು $1200 ಅಂತಿಮ ಬ್ಯಾಲೆನ್ಸ್ಗೆ ಕಾರಣವಾಗುತ್ತದೆ. ಆದರೆ ಸಮಕಾಲೀನ ಸನ್ನಿವೇಶದಲ್ಲಿ ಏನಾಗುತ್ತದೆ?
ಕಾರ್ಯಾಚರಣೆಗಳ ಸಂಭಾವ್ಯ ಇಂಟರ್ಲೀವ್:
- ಥ್ರೆಡ್ A: ಬ್ಯಾಲೆನ್ಸ್ ಓದುತ್ತದೆ ($1000).
- ಸಂದರ್ಭ ಸ್ವಿಚ್: ಆಪರೇಟಿಂಗ್ ಸಿಸ್ಟಮ್ ಥ್ರೆಡ್ A ಅನ್ನು ನಿಲ್ಲಿಸಿ ಥ್ರೆಡ್ B ಅನ್ನು ಚಲಾಯಿಸುತ್ತದೆ.
- ಥ್ರೆಡ್ B: ಬ್ಯಾಲೆನ್ಸ್ ಓದುತ್ತದೆ (ಇನ್ನೂ $1000).
- ಥ್ರೆಡ್ B: ತನ್ನ ಹೊಸ ಬ್ಯಾಲೆನ್ಸ್ ಅನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡುತ್ತದೆ ($1000 + $100 = $1100).
- ಥ್ರೆಡ್ B: ಹೊಸ ಬ್ಯಾಲೆನ್ಸ್ ($1100) ಅನ್ನು ಮೆಮೊರಿಗೆ ಮತ್ತೆ ಬರೆಯುತ್ತದೆ.
- ಸಂದರ್ಭ ಸ್ವಿಚ್: ಆಪರೇಟಿಂಗ್ ಸಿಸ್ಟಮ್ ಥ್ರೆಡ್ A ಅನ್ನು ಪುನರಾರಂಭಿಸುತ್ತದೆ.
- ಥ್ರೆಡ್ A: ಈ ಹಿಂದೆ ಓದಿದ ಮೌಲ್ಯದ ಆಧಾರದ ಮೇಲೆ ತನ್ನ ಹೊಸ ಬ್ಯಾಲೆನ್ಸ್ ಅನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡುತ್ತದೆ ($1000 + $100 = $1100).
- ಥ್ರೆಡ್ A: ಹೊಸ ಬ್ಯಾಲೆನ್ಸ್ ($1100) ಅನ್ನು ಮೆಮೊರಿಗೆ ಮತ್ತೆ ಬರೆಯುತ್ತದೆ.
ಅಂತಿಮ ಬ್ಯಾಲೆನ್ಸ್ $1100, ನಿರೀಕ್ಷಿತ $1200 ಅಲ್ಲ. ರೇಸ್ ಕಂಡೀಶನ್ ಕಾರಣದಿಂದಾಗಿ $100 ಠೇವಣಿ ಕಣ್ಮರೆಯಾಗಿದೆ. ಹಂಚಿಕೆಯ ಸಂಪನ್ಮೂಲವನ್ನು (ಖಾತೆಯ ಬ್ಯಾಲೆನ್ಸ್) ಪ್ರವೇಶಿಸುವ ಕೋಡ್ನ ಬ್ಲಾಕ್ ಅನ್ನು ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ (critical section) ಎಂದು ಕರೆಯಲಾಗುತ್ತದೆ. ರೇಸ್ ಕಂಡೀಶನ್ಗಳನ್ನು ತಡೆಗಟ್ಟಲು, ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ಕೇವಲ ಒಂದು ಥ್ರೆಡ್ ಮಾತ್ರ ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ನಲ್ಲಿ ಕಾರ್ಯಗತಗೊಳ್ಳುವುದನ್ನು ನಾವು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಬೇಕು. ಈ ತತ್ವವನ್ನು ಮ್ಯೂಚುಯಲ್ ಎಕ್ಸ್ಕ್ಲೂಷನ್ (mutual exclusion) ಎಂದು ಕರೆಯಲಾಗುತ್ತದೆ.
ಲಾಕ್-ಆಧಾರಿತ ಸಿಂಕ್ರೊನೈಸೇಶನ್ ಪರಿಚಯ
ಮ್ಯೂಚುಯಲ್ ಎಕ್ಸ್ಕ್ಲೂಷನ್ ಅನ್ನು ಜಾರಿಗೊಳಿಸಲು ಲಾಕ್-ಆಧಾರಿತ ಸಿಂಕ್ರೊನೈಸೇಶನ್ ಪ್ರಾಥಮಿಕ ಕಾರ್ಯವಿಧಾನವಾಗಿದೆ. ಲಾಕ್ (ಮ್ಯೂಟೆಕ್ಸ್ ಎಂದೂ ಕರೆಯುತ್ತಾರೆ) ಒಂದು ಸಿಂಕ್ರೊನೈಸೇಶನ್ ಪ್ರಿಮಿಟಿವ್ ಆಗಿದ್ದು ಅದು ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ಗೆ ಕಾವಲುಗಾರನಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ.
ಒಬ್ಬರಿಗೆ ಮಾತ್ರ ಪ್ರವೇಶವಿರುವ ಶೌಚಾಲಯದ ಕೀಲಿಯ ಸಾದೃಶ್ಯವು ಇಲ್ಲಿಗೆ ತುಂಬಾ ಸೂಕ್ತವಾಗಿದೆ. ಶೌಚಾಲಯವು ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್, ಮತ್ತು ಕೀಲಿಯು ಲಾಕ್ ಆಗಿದೆ. ಅನೇಕ ಜನರು (ಥ್ರೆಡ್ಗಳು) ಹೊರಗೆ ಕಾಯುತ್ತಿರಬಹುದು, ಆದರೆ ಕೀಲಿಯನ್ನು ಹಿಡಿದಿರುವ ವ್ಯಕ್ತಿ ಮಾತ್ರ ಒಳಗೆ ಪ್ರವೇಶಿಸಬಹುದು. ಅವರು ಮುಗಿದ ನಂತರ, ಅವರು ಹೊರಬಂದು ಕೀಲಿಯನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತಾರೆ, ಇದರಿಂದ ಸರದಿಯಲ್ಲಿರುವ ಮುಂದಿನ ವ್ಯಕ್ತಿ ಅದನ್ನು ತೆಗೆದುಕೊಂಡು ಪ್ರವೇಶಿಸಬಹುದು.
ಲಾಕ್ಗಳು ಎರಡು ಮೂಲಭೂತ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಬೆಂಬಲಿಸುತ್ತವೆ:
- ಅಕ್ವೈರ್ (ಅಥವಾ ಲಾಕ್): ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ಗೆ ಪ್ರವೇಶಿಸುವ ಮೊದಲು ಥ್ರೆಡ್ ಈ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ಕರೆಯುತ್ತದೆ. ಲಾಕ್ ಲಭ್ಯವಿದ್ದರೆ, ಥ್ರೆಡ್ ಅದನ್ನು ಪಡೆದುಕೊಳ್ಳುತ್ತದೆ ಮತ್ತು ಮುಂದುವರಿಯುತ್ತದೆ. ಲಾಕ್ ಅನ್ನು ಈಗಾಗಲೇ ಇನ್ನೊಂದು ಥ್ರೆಡ್ ಹಿಡಿದಿದ್ದರೆ, ಕರೆಯುವ ಥ್ರೆಡ್ ಲಾಕ್ ಬಿಡುಗಡೆಯಾಗುವವರೆಗೆ ಬ್ಲಾಕ್ (ಅಥವಾ "ಸ್ಲೀಪ್") ಆಗುತ್ತದೆ.
- ರಿಲೀಸ್ (ಅಥವಾ ಅನ್ಲಾಕ್): ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ ಅನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಿದ ನಂತರ ಥ್ರೆಡ್ ಈ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ಕರೆಯುತ್ತದೆ. ಇದು ಇತರ ಕಾಯುವ ಥ್ರೆಡ್ಗಳಿಗೆ ಲಾಕ್ ಅನ್ನು ಲಭ್ಯವಾಗುವಂತೆ ಮಾಡುತ್ತದೆ.
ನಮ್ಮ ಬ್ಯಾಂಕ್ ಖಾತೆಯ ತರ್ಕವನ್ನು ಲಾಕ್ನೊಂದಿಗೆ ಸುತ್ತುವರಿಯುವ ಮೂಲಕ, ನಾವು ಅದರ ಸರಿಯಾಗಿರುವುದನ್ನು ಖಾತರಿಪಡಿಸಬಹುದು:
acquire_lock(account_lock);
// --- ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ ಆರಂಭ ---
balance = read_balance();
new_balance = balance + amount;
write_balance(new_balance);
// --- ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ ಅಂತ್ಯ ---
release_lock(account_lock);
ಈಗ, ಥ್ರೆಡ್ A ಮೊದಲು ಲಾಕ್ ಪಡೆದರೆ, ಥ್ರೆಡ್ A ಎಲ್ಲಾ ಮೂರು ಹಂತಗಳನ್ನು ಪೂರ್ಣಗೊಳಿಸಿ ಲಾಕ್ ಅನ್ನು ಬಿಡುಗಡೆ ಮಾಡುವವರೆಗೆ ಥ್ರೆಡ್ B ಕಾಯಬೇಕಾಗುತ್ತದೆ. ಕಾರ್ಯಾಚರಣೆಗಳು ಇನ್ನು ಮುಂದೆ ಇಂಟರ್ಲೀವ್ ಆಗುವುದಿಲ್ಲ, ಮತ್ತು ರೇಸ್ ಕಂಡೀಶನ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ.
ಲಾಕ್ಗಳ ವಿಧಗಳು: ಪ್ರೋಗ್ರಾಮರ್ನ ಟೂಲ್ಕಿಟ್
ಲಾಕ್ನ ಮೂಲ ಪರಿಕಲ್ಪನೆಯು ಸರಳವಾಗಿದ್ದರೂ, ವಿಭಿನ್ನ ಸನ್ನಿವೇಶಗಳಿಗೆ ವಿಭಿನ್ನ ರೀತಿಯ ಲಾಕಿಂಗ್ ಕಾರ್ಯವಿಧಾನಗಳು ಬೇಕಾಗುತ್ತವೆ. ಸಮರ್ಥ ಮತ್ತು ಸರಿಯಾದ ಸಮಕಾಲೀನ ವ್ಯವಸ್ಥೆಗಳನ್ನು ನಿರ್ಮಿಸಲು ಲಭ್ಯವಿರುವ ಲಾಕ್ಗಳ ಟೂಲ್ಕಿಟ್ ಅನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು ಬಹಳ ಮುಖ್ಯ.
ಮ್ಯೂಟೆಕ್ಸ್ (ಮ್ಯೂಚುಯಲ್ ಎಕ್ಸ್ಕ್ಲೂಷನ್) ಲಾಕ್ಗಳು
ಮ್ಯೂಟೆಕ್ಸ್ ಅತ್ಯಂತ ಸರಳ ಮತ್ತು ಸಾಮಾನ್ಯ ರೀತಿಯ ಲಾಕ್ ಆಗಿದೆ. ಇದು ಬೈನರಿ ಲಾಕ್, ಅಂದರೆ ಇದು ಕೇವಲ ಎರಡು ಸ್ಥಿತಿಗಳನ್ನು ಹೊಂದಿದೆ: ಲಾಕ್ ಅಥವಾ ಅನ್ಲಾಕ್. ಇದನ್ನು ಕಟ್ಟುನಿಟ್ಟಾದ ಮ್ಯೂಚುಯಲ್ ಎಕ್ಸ್ಕ್ಲೂಷನ್ ಅನ್ನು ಜಾರಿಗೊಳಿಸಲು ವಿನ್ಯಾಸಗೊಳಿಸಲಾಗಿದೆ, ಯಾವುದೇ ಸಮಯದಲ್ಲಿ ಕೇವಲ ಒಂದು ಥ್ರೆಡ್ ಮಾತ್ರ ಲಾಕ್ ಅನ್ನು ಹೊಂದಿರಬಹುದೆಂದು ಖಚಿತಪಡಿಸುತ್ತದೆ.
- ಮಾಲೀಕತ್ವ: ಹೆಚ್ಚಿನ ಮ್ಯೂಟೆಕ್ಸ್ ಅನುಷ್ಠಾನಗಳ ಒಂದು ಪ್ರಮುಖ ಗುಣಲಕ್ಷಣವೆಂದರೆ ಮಾಲೀಕತ್ವ. ಮ್ಯೂಟೆಕ್ಸ್ ಅನ್ನು ಪಡೆದುಕೊಳ್ಳುವ ಥ್ರೆಡ್ ಮಾತ್ರ ಅದನ್ನು ಬಿಡುಗಡೆ ಮಾಡಲು ಅನುಮತಿಸಲಾದ ಥ್ರೆಡ್ ಆಗಿದೆ. ಇದು ಒಂದು ಥ್ರೆಡ್ ಇನ್ನೊಬ್ಬರು ಬಳಸುತ್ತಿರುವ ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ ಅನ್ನು ಅಜಾಗರೂಕತೆಯಿಂದ (ಅಥವಾ ದುರುದ್ದೇಶಪೂರ್ವಕವಾಗಿ) ಅನ್ಲಾಕ್ ಮಾಡುವುದನ್ನು ತಡೆಯುತ್ತದೆ.
- ಬಳಕೆಯ ಸಂದರ್ಭ: ಹಂಚಿಕೆಯ ವೇರಿಯೇಬಲ್ ಅನ್ನು ನವೀಕರಿಸುವುದು ಅಥವಾ ಡೇಟಾ ರಚನೆಯನ್ನು ಮಾರ್ಪಡಿಸುವಂತಹ ಸಣ್ಣ, ಸರಳ ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ಗಳನ್ನು ರಕ್ಷಿಸಲು ಮ್ಯೂಟೆಕ್ಸ್ಗಳು ಡೀಫಾಲ್ಟ್ ಆಯ್ಕೆಯಾಗಿದೆ.
ಸೆಮಾಫೋರ್ಗಳು
ಸೆಮಾಫೋರ್ ಡಚ್ ಕಂಪ್ಯೂಟರ್ ವಿಜ್ಞಾನಿ ಎಡ್ಸ್ಗರ್ ಡಬ್ಲ್ಯೂ. ಡಿಜ್ಕ್ಸ್ಟ್ರಾ ಅವರಿಂದ ಆವಿಷ್ಕರಿಸಲ್ಪಟ್ಟ ಹೆಚ್ಚು ಸಾಮಾನ್ಯೀಕರಿಸಿದ ಸಿಂಕ್ರೊನೈಸೇಶನ್ ಪ್ರಿಮಿಟಿವ್ ಆಗಿದೆ. ಮ್ಯೂಟೆಕ್ಸ್ಗಿಂತ ಭಿನ್ನವಾಗಿ, ಸೆಮಾಫೋರ್ ಧನಾತ್ಮಕವಲ್ಲದ ಪೂರ್ಣಾಂಕ ಮೌಲ್ಯದ ಕೌಂಟರ್ ಅನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ.
ಇದು ಎರಡು ಅಟಾಮಿಕ್ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ:
- wait() (ಅಥವಾ P ಕಾರ್ಯಾಚರಣೆ): ಸೆಮಾಫೋರ್ನ ಕೌಂಟರ್ ಅನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ. ಕೌಂಟರ್ ಋಣಾತ್ಮಕವಾದರೆ, ಕೌಂಟರ್ ಶೂನ್ಯಕ್ಕಿಂತ ಹೆಚ್ಚಾಗುವವರೆಗೆ ಅಥವಾ ಸಮನಾಗುವವರೆಗೆ ಥ್ರೆಡ್ ಬ್ಲಾಕ್ ಆಗುತ್ತದೆ.
- signal() (ಅಥವಾ V ಕಾರ್ಯಾಚರಣೆ): ಸೆಮಾಫೋರ್ನ ಕೌಂಟರ್ ಅನ್ನು ಹೆಚ್ಚಿಸುತ್ತದೆ. ಸೆಮಾಫೋರ್ನಲ್ಲಿ ಯಾವುದೇ ಥ್ರೆಡ್ಗಳು ಬ್ಲಾಕ್ ಆಗಿದ್ದರೆ, ಅವುಗಳಲ್ಲಿ ಒಂದನ್ನು ಅನ್ಬ್ಲಾಕ್ ಮಾಡಲಾಗುತ್ತದೆ.
ಸೆಮಾಫೋರ್ಗಳಲ್ಲಿ ಎರಡು ಮುಖ್ಯ ವಿಧಗಳಿವೆ:
- ಬೈನರಿ ಸೆಮಾಫೋರ್: ಕೌಂಟರ್ ಅನ್ನು 1 ಕ್ಕೆ ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತದೆ. ಇದು ಕೇವಲ 0 ಅಥವಾ 1 ಆಗಿರಬಹುದು, ಇದು ಕ್ರಿಯಾತ್ಮಕವಾಗಿ ಮ್ಯೂಟೆಕ್ಸ್ಗೆ ಸಮನಾಗಿರುತ್ತದೆ.
- ಕೌಂಟಿಂಗ್ ಸೆಮಾಫೋರ್: ಕೌಂಟರ್ ಅನ್ನು ಯಾವುದೇ ಪೂರ್ಣಾಂಕ N > 1 ಗೆ ಪ್ರಾರಂಭಿಸಬಹುದು. ಇದು N ಥ್ರೆಡ್ಗಳವರೆಗೆ ಏಕಕಾಲದಲ್ಲಿ ಸಂಪನ್ಮೂಲವನ್ನು ಪ್ರವೇಶಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದನ್ನು ಸೀಮಿತ ಸಂಪನ್ಮೂಲಗಳ ಪೂಲ್ಗೆ ಪ್ರವೇಶವನ್ನು ನಿಯಂತ್ರಿಸಲು ಬಳಸಲಾಗುತ್ತದೆ.
ಉದಾಹರಣೆ: ಗರಿಷ್ಠ 10 ಸಮಕಾಲೀನ ಡೇಟಾಬೇಸ್ ಸಂಪರ್ಕಗಳನ್ನು ನಿಭಾಯಿಸಬಲ್ಲ ಕನೆಕ್ಷನ್ ಪೂಲ್ ಹೊಂದಿರುವ ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಕಲ್ಪಿಸಿಕೊಳ್ಳಿ. 10 ಕ್ಕೆ ಪ್ರಾರಂಭಿಸಲಾದ ಕೌಂಟಿಂಗ್ ಸೆಮಾಫೋರ್ ಇದನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ನಿರ್ವಹಿಸಬಹುದು. ಪ್ರತಿಯೊಂದು ಥ್ರೆಡ್ ಸಂಪರ್ಕವನ್ನು ತೆಗೆದುಕೊಳ್ಳುವ ಮೊದಲು ಸೆಮಾಫೋರ್ನಲ್ಲಿ `wait()` ಅನ್ನು ನಿರ್ವಹಿಸಬೇಕು. 11 ನೇ ಥ್ರೆಡ್ ಮೊದಲ 10 ಥ್ರೆಡ್ಗಳಲ್ಲಿ ಒಂದು ತನ್ನ ಡೇಟಾಬೇಸ್ ಕೆಲಸವನ್ನು ಮುಗಿಸಿ ಸೆಮಾಫೋರ್ನಲ್ಲಿ `signal()` ಅನ್ನು ನಿರ್ವಹಿಸುವವರೆಗೆ ಬ್ಲಾಕ್ ಆಗುತ್ತದೆ, ಇದರಿಂದ ಸಂಪರ್ಕವು ಪೂಲ್ಗೆ ಹಿಂತಿರುಗುತ್ತದೆ.
ರೀಡ್-ರೈಟ್ ಲಾಕ್ಗಳು (ಹಂಚಿಕೆಯ/ವಿಶೇಷ ಲಾಕ್ಗಳು)
ಸಮಕಾಲೀನ ವ್ಯವಸ್ಥೆಗಳಲ್ಲಿ ಒಂದು ಸಾಮಾನ್ಯ ಮಾದರಿಯೆಂದರೆ ಡೇಟಾವನ್ನು ಬರೆಯುವುದಕ್ಕಿಂತ ಹೆಚ್ಚಾಗಿ ಓದಲಾಗುತ್ತದೆ. ಈ ಸನ್ನಿವೇಶದಲ್ಲಿ ಸರಳ ಮ್ಯೂಟೆಕ್ಸ್ ಬಳಸುವುದು ಅಸಮರ್ಥವಾಗಿದೆ, ಏಕೆಂದರೆ ಇದು ಅನೇಕ ಥ್ರೆಡ್ಗಳು ಏಕಕಾಲದಲ್ಲಿ ಡೇಟಾವನ್ನು ಓದುವುದನ್ನು ತಡೆಯುತ್ತದೆ, ಆದರೂ ಓದುವುದು ಸುರಕ್ಷಿತ, ಮಾರ್ಪಡಿಸದ ಕಾರ್ಯಾಚರಣೆಯಾಗಿದೆ.
ರೀಡ್-ರೈಟ್ ಲಾಕ್ ಎರಡು ಲಾಕಿಂಗ್ ಮೋಡ್ಗಳನ್ನು ಒದಗಿಸುವ ಮೂಲಕ ಇದನ್ನು ಪರಿಹರಿಸುತ್ತದೆ:
- ಹಂಚಿಕೆಯ (ರೀಡ್) ಲಾಕ್: ಯಾವುದೇ ಥ್ರೆಡ್ ರೈಟ್ ಲಾಕ್ ಅನ್ನು ಹೊಂದಿರದವರೆಗೆ, ಅನೇಕ ಥ್ರೆಡ್ಗಳು ಏಕಕಾಲದಲ್ಲಿ ರೀಡ್ ಲಾಕ್ ಅನ್ನು ಪಡೆದುಕೊಳ್ಳಬಹುದು. ಇದು ಹೆಚ್ಚಿನ-ಸಮಕಾಲೀನ ಓದುವಿಕೆಗೆ ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ.
- ವಿಶೇಷ (ರೈಟ್) ಲಾಕ್: ಒಂದು ಸಮಯದಲ್ಲಿ ಕೇವಲ ಒಂದು ಥ್ರೆಡ್ ಮಾತ್ರ ರೈಟ್ ಲಾಕ್ ಅನ್ನು ಪಡೆದುಕೊಳ್ಳಬಹುದು. ಒಂದು ಥ್ರೆಡ್ ರೈಟ್ ಲಾಕ್ ಅನ್ನು ಹೊಂದಿರುವಾಗ, ಇತರ ಎಲ್ಲಾ ಥ್ರೆಡ್ಗಳು (ರೀಡರ್ಗಳು ಮತ್ತು ರೈಟರ್ಗಳು ಎರಡೂ) ಬ್ಲಾಕ್ ಆಗುತ್ತವೆ.
ಹಂಚಿಕೆಯ ಗ್ರಂಥಾಲಯದಲ್ಲಿನ ಡಾಕ್ಯುಮೆಂಟ್ ಇದಕ್ಕೆ ಉತ್ತಮ ಸಾದೃಶ್ಯವಾಗಿದೆ. ಅನೇಕ ಜನರು ಒಂದೇ ಸಮಯದಲ್ಲಿ ಡಾಕ್ಯುಮೆಂಟ್ನ ಪ್ರತಿಗಳನ್ನು ಓದಬಹುದು (ಹಂಚಿಕೆಯ ರೀಡ್ ಲಾಕ್). ಆದಾಗ್ಯೂ, ಯಾರಾದರೂ ಡಾಕ್ಯುಮೆಂಟ್ ಅನ್ನು ಸಂಪಾದಿಸಲು ಬಯಸಿದರೆ, ಅವರು ಅದನ್ನು ಪ್ರತ್ಯೇಕವಾಗಿ ತೆಗೆದುಕೊಳ್ಳಬೇಕು, ಮತ್ತು ಅವರು ಮುಗಿಸುವವರೆಗೆ ಬೇರೆ ಯಾರೂ ಅದನ್ನು ಓದಲು ಅಥವಾ ಸಂಪಾದಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ (ವಿಶೇಷ ರೈಟ್ ಲಾಕ್).
ರಿಕರ್ಸಿವ್ ಲಾಕ್ಗಳು (ರಿಎಂಟ್ರೆಂಟ್ ಲಾಕ್ಗಳು)
ಈಗಾಗಲೇ ಮ್ಯೂಟೆಕ್ಸ್ ಹೊಂದಿರುವ ಥ್ರೆಡ್ ಅದನ್ನು ಮತ್ತೆ ಪಡೆಯಲು ಪ್ರಯತ್ನಿಸಿದರೆ ಏನಾಗುತ್ತದೆ? ಸಾಮಾನ್ಯ ಮ್ಯೂಟೆಕ್ಸ್ನೊಂದಿಗೆ, ಇದು ತಕ್ಷಣದ ಡೆಡ್ಲಾಕ್ಗೆ ಕಾರಣವಾಗುತ್ತದೆ—ಥ್ರೆಡ್ ತನ್ನಷ್ಟಕ್ಕೆ ತಾನೇ ಲಾಕ್ ಅನ್ನು ಬಿಡುಗಡೆ ಮಾಡಲು ಶಾಶ್ವತವಾಗಿ ಕಾಯುತ್ತದೆ. ಈ ಸಮಸ್ಯೆಯನ್ನು ಪರಿಹರಿಸಲು ರಿಕರ್ಸಿವ್ ಲಾಕ್ (ಅಥವಾ ರಿಎಂಟ್ರೆಂಟ್ ಲಾಕ್) ಅನ್ನು ವಿನ್ಯಾಸಗೊಳಿಸಲಾಗಿದೆ.
ರಿಕರ್ಸಿವ್ ಲಾಕ್ ಒಂದೇ ಥ್ರೆಡ್ಗೆ ಒಂದೇ ಲಾಕ್ ಅನ್ನು ಹಲವು ಬಾರಿ ಪಡೆಯಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದು ಆಂತರಿಕ ಮಾಲೀಕತ್ವ ಕೌಂಟರ್ ಅನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ. ಮಾಲೀಕತ್ವದ ಥ್ರೆಡ್ `acquire()` ಎಂದು ಕರೆದಷ್ಟು ಬಾರಿ `release()` ಎಂದು ಕರೆದಾಗ ಮಾತ್ರ ಲಾಕ್ ಸಂಪೂರ್ಣವಾಗಿ ಬಿಡುಗಡೆಯಾಗುತ್ತದೆ. ಇದು ತಮ್ಮ ಕಾರ್ಯಗತಗೊಳಿಸುವಿಕೆಯ ಸಮಯದಲ್ಲಿ ಹಂಚಿಕೆಯ ಸಂಪನ್ಮೂಲವನ್ನು ರಕ್ಷಿಸಬೇಕಾದ ರಿಕರ್ಸಿವ್ ಫಂಕ್ಷನ್ಗಳಲ್ಲಿ ವಿಶೇಷವಾಗಿ ಉಪಯುಕ್ತವಾಗಿದೆ.
ಲಾಕಿಂಗ್ನ ಅಪಾಯಗಳು: ಸಾಮಾನ್ಯ ಮೋಸಗಳು
ಲಾಕ್ಗಳು ಶಕ್ತಿಯುತವಾಗಿದ್ದರೂ, ಅವು ಎರಡು-ಬದಿಯ ಕತ್ತಿಯಿದ್ದಂತೆ. ಲಾಕ್ಗಳ ಅನುಚಿತ ಬಳಕೆಯು ಸರಳ ರೇಸ್ ಕಂಡೀಶನ್ಗಳಿಗಿಂತ ಹೆಚ್ಚು ಕಷ್ಟಕರವಾದ ದೋಷಗಳಿಗೆ ಕಾರಣವಾಗಬಹುದು. ಇವುಗಳಲ್ಲಿ ಡೆಡ್ಲಾಕ್ಗಳು, ಲೈವ್ಲಾಕ್ಗಳು, ಮತ್ತು ಕಾರ್ಯಕ್ಷಮತೆಯ ಅಡಚಣೆಗಳು ಸೇರಿವೆ.
ಡೆಡ್ಲಾಕ್
ಸಮಕಾಲೀನ ಪ್ರೋಗ್ರಾಮಿಂಗ್ನಲ್ಲಿ ಡೆಡ್ಲಾಕ್ ಅತ್ಯಂತ ಭಯಪಡುವ ಸನ್ನಿವೇಶವಾಗಿದೆ. ಎರಡು ಅಥವಾ ಅದಕ್ಕಿಂತ ಹೆಚ್ಚು ಥ್ರೆಡ್ಗಳು ಅನಿರ್ದಿಷ್ಟವಾಗಿ ಬ್ಲಾಕ್ ಆದಾಗ ಇದು ಸಂಭವಿಸುತ್ತದೆ, ಪ್ರತಿಯೊಂದೂ ಅದೇ ಗುಂಪಿನಲ್ಲಿನ ಇನ್ನೊಂದು ಥ್ರೆಡ್ ಹಿಡಿದಿರುವ ಸಂಪನ್ಮೂಲಕ್ಕಾಗಿ ಕಾಯುತ್ತಿರುತ್ತದೆ.
ಎರಡು ಥ್ರೆಡ್ಗಳು (ಥ್ರೆಡ್ 1, ಥ್ರೆಡ್ 2) ಮತ್ತು ಎರಡು ಲಾಕ್ಗಳ (ಲಾಕ್ A, ಲಾಕ್ B) ಸರಳ ಸನ್ನಿವೇಶವನ್ನು ಪರಿಗಣಿಸಿ:
- ಥ್ರೆಡ್ 1 ಲಾಕ್ A ಅನ್ನು ಪಡೆದುಕೊಳ್ಳುತ್ತದೆ.
- ಥ್ರೆಡ್ 2 ಲಾಕ್ B ಅನ್ನು ಪಡೆದುಕೊಳ್ಳುತ್ತದೆ.
- ಥ್ರೆಡ್ 1 ಈಗ ಲಾಕ್ B ಅನ್ನು ಪಡೆಯಲು ಪ್ರಯತ್ನಿಸುತ್ತದೆ, ಆದರೆ ಅದನ್ನು ಥ್ರೆಡ್ 2 ಹಿಡಿದಿರುವುದರಿಂದ, ಥ್ರೆಡ್ 1 ಬ್ಲಾಕ್ ಆಗುತ್ತದೆ.
- ಥ್ರೆಡ್ 2 ಈಗ ಲಾಕ್ A ಅನ್ನು ಪಡೆಯಲು ಪ್ರಯತ್ನಿಸುತ್ತದೆ, ಆದರೆ ಅದನ್ನು ಥ್ರೆಡ್ 1 ಹಿಡಿದಿರುವುದರಿಂದ, ಥ್ರೆಡ್ 2 ಬ್ಲಾಕ್ ಆಗುತ್ತದೆ.
ಎರಡೂ ಥ್ರೆಡ್ಗಳು ಈಗ ಶಾಶ್ವತ ಕಾಯುವ ಸ್ಥಿತಿಯಲ್ಲಿ ಸಿಲುಕಿಕೊಂಡಿವೆ. ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಗಿತಗೊಳ್ಳುತ್ತದೆ. ಈ ಪರಿಸ್ಥಿತಿಯು ನಾಲ್ಕು ಅಗತ್ಯ ಪರಿಸ್ಥಿತಿಗಳ (ಕಾಫ್ಮನ್ ಪರಿಸ್ಥಿತಿಗಳು) ಇರುವಿಕೆಯಿಂದ ಉದ್ಭವಿಸುತ್ತದೆ:
- ಮ್ಯೂಚುಯಲ್ ಎಕ್ಸ್ಕ್ಲೂಷನ್: ಸಂಪನ್ಮೂಲಗಳನ್ನು (ಲಾಕ್ಗಳನ್ನು) ಹಂಚಿಕೊಳ್ಳಲು ಸಾಧ್ಯವಿಲ್ಲ.
- ಹಿಡಿದಿಟ್ಟು ಕಾಯುವುದು: ಒಂದು ಥ್ರೆಡ್ ಇನ್ನೊಂದಕ್ಕಾಗಿ ಕಾಯುತ್ತಿರುವಾಗ ಕನಿಷ್ಠ ಒಂದು ಸಂಪನ್ಮೂಲವನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಂಡಿರುತ್ತದೆ.
- ಪೂರ್ವ-ತೆರವು ಇಲ್ಲದಿರುವುದು: ಸಂಪನ್ಮೂಲವನ್ನು ಹಿಡಿದಿರುವ ಥ್ರೆಡ್ನಿಂದ ಬಲವಂತವಾಗಿ ತೆಗೆದುಕೊಳ್ಳಲು ಸಾಧ್ಯವಿಲ್ಲ.
- ವೃತ್ತಾಕಾರದ ಕಾಯುವಿಕೆ: ಎರಡು ಅಥವಾ ಅದಕ್ಕಿಂತ ಹೆಚ್ಚು ಥ್ರೆಡ್ಗಳ ಸರಪಳಿ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ, ಅಲ್ಲಿ ಪ್ರತಿಯೊಂದು ಥ್ರೆಡ್ ಸರಪಳಿಯಲ್ಲಿನ ಮುಂದಿನ ಥ್ರೆಡ್ ಹಿಡಿದಿರುವ ಸಂಪನ್ಮೂಲಕ್ಕಾಗಿ ಕಾಯುತ್ತಿದೆ.
ಡೆಡ್ಲಾಕ್ ಅನ್ನು ತಡೆಗಟ್ಟುವುದು ಈ ಪರಿಸ್ಥಿತಿಗಳಲ್ಲಿ ಕನಿಷ್ಠ ಒಂದನ್ನು ಮುರಿಯುವುದನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ. ಲಾಕ್ ಸ್ವಾಧೀನಕ್ಕೆ ಕಟ್ಟುನಿಟ್ಟಾದ ಜಾಗತಿಕ ಕ್ರಮವನ್ನು ಜಾರಿಗೊಳಿಸುವ ಮೂಲಕ ವೃತ್ತಾಕಾರದ ಕಾಯುವಿಕೆ ಪರಿಸ್ಥಿತಿಯನ್ನು ಮುರಿಯುವುದು ಅತ್ಯಂತ ಸಾಮಾನ್ಯ ತಂತ್ರವಾಗಿದೆ.
ಲೈವ್ಲಾಕ್
ಲೈವ್ಲಾಕ್ ಡೆಡ್ಲಾಕ್ನ ಹೆಚ್ಚು ಸೂಕ್ಷ್ಮವಾದ ಸಂಬಂಧಿಯಾಗಿದೆ. ಲೈವ್ಲಾಕ್ನಲ್ಲಿ, ಥ್ರೆಡ್ಗಳು ಬ್ಲಾಕ್ ಆಗಿರುವುದಿಲ್ಲ—ಅವು ಸಕ್ರಿಯವಾಗಿ ಚಾಲನೆಯಲ್ಲಿರುತ್ತವೆ—ಆದರೆ ಅವು ಯಾವುದೇ ಪ್ರಗತಿಯನ್ನು ಸಾಧಿಸುವುದಿಲ್ಲ. ಯಾವುದೇ ಉಪಯುಕ್ತ ಕೆಲಸವನ್ನು ಮಾಡದೆ, ಅವು ಪರಸ್ಪರರ ಸ್ಥಿತಿ ಬದಲಾವಣೆಗಳಿಗೆ ಪ್ರತಿಕ್ರಿಯಿಸುವ ಚಕ್ರದಲ್ಲಿ ಸಿಲುಕಿಕೊಂಡಿರುತ್ತವೆ.
ಇಕ್ಕಟ್ಟಾದ ಹಜಾರದಲ್ಲಿ ಇಬ್ಬರು ಪರಸ್ಪರ ದಾಟಲು ಪ್ರಯತ್ನಿಸುವುದು ಇದಕ್ಕೆ ಒಂದು ಶ್ರೇಷ್ಠ ಸಾದೃಶ್ಯವಾಗಿದೆ. ಇಬ್ಬರೂ ಸಭ್ಯರಾಗಿರಲು ಪ್ರಯತ್ನಿಸಿ ತಮ್ಮ ಎಡಕ್ಕೆ ಸರಿಯುತ್ತಾರೆ, ಆದರೆ ಅವರು ಪರಸ್ಪರ ದಾರಿಯನ್ನು ತಡೆಯುತ್ತಾರೆ. ನಂತರ ಇಬ್ಬರೂ ತಮ್ಮ ಬಲಕ್ಕೆ ಸರಿಯುತ್ತಾರೆ, ಮತ್ತೆ ಪರಸ್ಪರ ದಾರಿಯನ್ನು ತಡೆಯುತ್ತಾರೆ. ಅವರು ಸಕ್ರಿಯವಾಗಿ ಚಲಿಸುತ್ತಿದ್ದಾರೆ ಆದರೆ ಹಜಾರದಲ್ಲಿ ಮುಂದೆ ಸಾಗುತ್ತಿಲ್ಲ. ಸಾಫ್ಟ್ವೇರ್ನಲ್ಲಿ, ಇದು ಕಳಪೆಯಾಗಿ ವಿನ್ಯಾಸಗೊಳಿಸಲಾದ ಡೆಡ್ಲಾಕ್ ಚೇತರಿಕೆ ಕಾರ್ಯವಿಧಾನಗಳೊಂದಿಗೆ ಸಂಭವಿಸಬಹುದು, ಅಲ್ಲಿ ಥ್ರೆಡ್ಗಳು ಪದೇ ಪದೇ ಹಿಂದೆ ಸರಿದು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸುತ್ತವೆ, ಕೇವಲ ಮತ್ತೆ ಸಂಘರ್ಷಕ್ಕೆ ಒಳಗಾಗಲು.
ಸ್ಟಾರ್ವೇಷನ್
ಸಂಪನ್ಮೂಲವು ಲಭ್ಯವಾದರೂ, ಒಂದು ಥ್ರೆಡ್ಗೆ ಅಗತ್ಯವಾದ ಸಂಪನ್ಮೂಲಕ್ಕೆ ಪ್ರವೇಶವನ್ನು ನಿರಂತರವಾಗಿ ನಿರಾಕರಿಸಿದಾಗ ಸ್ಟಾರ್ವೇಷನ್ ಸಂಭವಿಸುತ್ತದೆ. ಇದು "ನ್ಯಾಯಯುತ"ವಲ್ಲದ ಶೆಡ್ಯೂಲಿಂಗ್ ಅಲ್ಗಾರಿದಮ್ಗಳನ್ನು ಹೊಂದಿರುವ ವ್ಯವಸ್ಥೆಗಳಲ್ಲಿ ಸಂಭವಿಸಬಹುದು. ಉದಾಹರಣೆಗೆ, ಲಾಕಿಂಗ್ ಕಾರ್ಯವಿಧಾನವು ಯಾವಾಗಲೂ ಉನ್ನತ-ಆದ್ಯತೆಯ ಥ್ರೆಡ್ಗಳಿಗೆ ಪ್ರವೇಶವನ್ನು ನೀಡಿದರೆ, ನಿರಂತರವಾಗಿ ಉನ್ನತ-ಆದ್ಯತೆಯ ಸ್ಪರ್ಧಿಗಳಿದ್ದರೆ ಕಡಿಮೆ-ಆದ್ಯತೆಯ ಥ್ರೆಡ್ಗೆ ಚಲಾಯಿಸಲು ಅವಕಾಶವೇ ಸಿಗದಿರಬಹುದು.
ಕಾರ್ಯಕ್ಷಮತೆಯ ಓವರ್ಹೆಡ್
ಲಾಕ್ಗಳು ಉಚಿತವಲ್ಲ. ಅವು ಹಲವಾರು ವಿಧಗಳಲ್ಲಿ ಕಾರ್ಯಕ್ಷಮತೆಯ ಓವರ್ಹೆಡ್ ಅನ್ನು ಪರಿಚಯಿಸುತ್ತವೆ:
- ಸ್ವಾಧೀನ/ಬಿಡುಗಡೆ ವೆಚ್ಚ: ಲಾಕ್ ಅನ್ನು ಸ್ವಾಧೀನಪಡಿಸಿಕೊಳ್ಳುವ ಮತ್ತು ಬಿಡುಗಡೆ ಮಾಡುವ ಕ್ರಿಯೆಯು ಅಟಾಮಿಕ್ ಕಾರ್ಯಾಚರಣೆಗಳು ಮತ್ತು ಮೆಮೊರಿ ಫೆನ್ಸ್ಗಳನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ, ಇವು ಸಾಮಾನ್ಯ ಸೂಚನೆಗಳಿಗಿಂತ ಹೆಚ್ಚು ಗಣನಾತ್ಮಕವಾಗಿ ದುಬಾರಿಯಾಗಿವೆ.
- ಸ್ಪರ್ಧೆ: ಅನೇಕ ಥ್ರೆಡ್ಗಳು ಒಂದೇ ಲಾಕ್ಗಾಗಿ ಆಗಾಗ್ಗೆ ಸ್ಪರ್ಧಿಸುತ್ತಿರುವಾಗ, ಸಿಸ್ಟಮ್ ಉತ್ಪಾದಕ ಕೆಲಸವನ್ನು ಮಾಡುವುದಕ್ಕಿಂತ ಹೆಚ್ಚಾಗಿ ಸಂದರ್ಭ ಸ್ವಿಚಿಂಗ್ ಮತ್ತು ಥ್ರೆಡ್ಗಳನ್ನು ಶೆಡ್ಯೂಲ್ ಮಾಡುವುದರಲ್ಲಿ ಗಣನೀಯ ಸಮಯವನ್ನು ಕಳೆಯುತ್ತದೆ. ಹೆಚ್ಚಿನ ಸ್ಪರ್ಧೆಯು ಪರಿಣಾಮಕಾರಿಯಾಗಿ ಕಾರ್ಯಗತಗೊಳಿಸುವಿಕೆಯನ್ನು ಸರಣೀಕರಿಸುತ್ತದೆ, ಇದು ಪ್ಯಾರಲಲಿಸಂನ ಉದ್ದೇಶವನ್ನು ಸೋಲಿಸುತ್ತದೆ.
ಲಾಕ್-ಆಧಾರಿತ ಸಿಂಕ್ರೊನೈಸೇಶನ್ಗಾಗಿ ಉತ್ತಮ ಅಭ್ಯಾಸಗಳು
ಲಾಕ್ಗಳೊಂದಿಗೆ ಸರಿಯಾದ ಮತ್ತು ಸಮರ್ಥವಾದ ಸಮಕಾಲೀನ ಕೋಡ್ ಬರೆಯಲು ಶಿಸ್ತು ಮತ್ತು ಉತ್ತಮ ಅಭ್ಯಾಸಗಳ ಗುಂಪಿಗೆ ಬದ್ಧತೆಯ ಅಗತ್ಯವಿದೆ. ಈ ತತ್ವಗಳು ಪ್ರೋಗ್ರಾಮಿಂಗ್ ಭಾಷೆ ಅಥವಾ ಪ್ಲಾಟ್ಫಾರ್ಮ್ ಅನ್ನು ಲೆಕ್ಕಿಸದೆ ಸಾರ್ವತ್ರಿಕವಾಗಿ ಅನ್ವಯಿಸುತ್ತವೆ.
1. ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ಗಳನ್ನು ಚಿಕ್ಕದಾಗಿಡಿ
ಲಾಕ್ ಅನ್ನು ಸಾಧ್ಯವಾದಷ್ಟು ಕಡಿಮೆ ಅವಧಿಗೆ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಬೇಕು. ನಿಮ್ಮ ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ ಸಮಕಾಲೀನ ಪ್ರವೇಶದಿಂದ ಸಂಪೂರ್ಣವಾಗಿ ರಕ್ಷಿಸಬೇಕಾದ ಕೋಡ್ ಅನ್ನು ಮಾತ್ರ ಹೊಂದಿರಬೇಕು. ಯಾವುದೇ ನಿರ್ಣಾಯಕವಲ್ಲದ ಕಾರ್ಯಾಚರಣೆಗಳನ್ನು (I/O, ಹಂಚಿಕೆಯ ಸ್ಥಿತಿಯನ್ನು ಒಳಗೊಂಡಿರದ ಸಂಕೀರ್ಣ ಲೆಕ್ಕಾಚಾರಗಳಂತಹ) ಲಾಕ್ ಮಾಡಿದ ಪ್ರದೇಶದ ಹೊರಗೆ ನಿರ್ವಹಿಸಬೇಕು. ನೀವು ಲಾಕ್ ಅನ್ನು ಹೆಚ್ಚು ಹೊತ್ತು ಹಿಡಿದಿಟ್ಟುಕೊಂಡಷ್ಟೂ, ಸ್ಪರ್ಧೆಯ ಸಾಧ್ಯತೆ ಹೆಚ್ಚಾಗುತ್ತದೆ ಮತ್ತು ನೀವು ಇತರ ಥ್ರೆಡ್ಗಳನ್ನು ಹೆಚ್ಚು ಬ್ಲಾಕ್ ಮಾಡುತ್ತೀರಿ.
2. ಸರಿಯಾದ ಲಾಕ್ ಗ್ರ್ಯಾನ್ಯುಲಾರಿಟಿಯನ್ನು ಆರಿಸಿ
ಲಾಕ್ ಗ್ರ್ಯಾನ್ಯುಲಾರಿಟಿ ಎಂದರೆ ಒಂದೇ ಲಾಕ್ನಿಂದ ರಕ್ಷಿಸಲ್ಪಟ್ಟ ಡೇಟಾದ ಪ್ರಮಾಣವನ್ನು ಸೂಚಿಸುತ್ತದೆ.
- ಒರಟು-ಧಾನ್ಯದ ಲಾಕಿಂಗ್ (Coarse-Grained Locking): ದೊಡ್ಡ ಡೇಟಾ ರಚನೆ ಅಥವಾ ಸಂಪೂರ್ಣ ಉಪವ್ಯವಸ್ಥೆಯನ್ನು ರಕ್ಷಿಸಲು ಒಂದೇ ಲಾಕ್ ಅನ್ನು ಬಳಸುವುದು. ಇದನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲು ಮತ್ತು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಸರಳವಾಗಿದೆ ಆದರೆ ಹೆಚ್ಚಿನ ಸ್ಪರ್ಧೆಗೆ ಕಾರಣವಾಗಬಹುದು, ಏಕೆಂದರೆ ಡೇಟಾದ ವಿವಿಧ ಭಾಗಗಳಲ್ಲಿನ ಸಂಬಂಧವಿಲ್ಲದ ಕಾರ್ಯಾಚರಣೆಗಳೆಲ್ಲವೂ ಒಂದೇ ಲಾಕ್ನಿಂದ ಸರಣೀಕರಿಸಲ್ಪಡುತ್ತವೆ.
- ಸೂಕ್ಷ್ಮ-ಧಾನ್ಯದ ಲಾಕಿಂಗ್ (Fine-Grained Locking): ಡೇಟಾ ರಚನೆಯ ವಿಭಿನ್ನ, ಸ್ವತಂತ್ರ ಭಾಗಗಳನ್ನು ರಕ್ಷಿಸಲು ಬಹು ಲಾಕ್ಗಳನ್ನು ಬಳಸುವುದು. ಉದಾಹರಣೆಗೆ, ಸಂಪೂರ್ಣ ಹ್ಯಾಶ್ ಟೇಬಲ್ಗೆ ಒಂದು ಲಾಕ್ ಬದಲಿಗೆ, ನೀವು ಪ್ರತಿ ಬಕೆಟ್ಗೆ ಪ್ರತ್ಯೇಕ ಲಾಕ್ ಅನ್ನು ಹೊಂದಬಹುದು. ಇದು ಹೆಚ್ಚು ಸಂಕೀರ್ಣವಾಗಿದೆ ಆದರೆ ಹೆಚ್ಚು ನೈಜ ಪ್ಯಾರಲಲಿಸಂ ಅನ್ನು ಅನುಮತಿಸುವ ಮೂಲಕ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ನಾಟಕೀಯವಾಗಿ ಸುಧಾರಿಸಬಹುದು.
ಅವುಗಳ ನಡುವಿನ ಆಯ್ಕೆಯು ಸರಳತೆ ಮತ್ತು ಕಾರ್ಯಕ್ಷಮತೆಯ ನಡುವಿನ ವಿನಿಮಯವಾಗಿದೆ. ಒರಟು ಲಾಕ್ಗಳೊಂದಿಗೆ ಪ್ರಾರಂಭಿಸಿ ಮತ್ತು ಕಾರ್ಯಕ್ಷಮತೆಯ ಪ್ರೊಫೈಲಿಂಗ್ ಲಾಕ್ ಸ್ಪರ್ಧೆಯು ಒಂದು ಅಡಚಣೆಯಾಗಿದೆ ಎಂದು ತೋರಿಸಿದರೆ ಮಾತ್ರ ಸೂಕ್ಷ್ಮ-ಧಾನ್ಯದ ಲಾಕ್ಗಳಿಗೆ ತೆರಳಿ.
3. ಯಾವಾಗಲೂ ನಿಮ್ಮ ಲಾಕ್ಗಳನ್ನು ಬಿಡುಗಡೆ ಮಾಡಿ
ಲಾಕ್ ಅನ್ನು ಬಿಡುಗಡೆ ಮಾಡಲು ವಿಫಲವಾದರೆ ಅದು ನಿಮ್ಮ ಸಿಸ್ಟಮ್ ಅನ್ನು ಸ್ಥಗಿತಗೊಳಿಸುವ ದುರಂತ ದೋಷವಾಗಿದೆ. ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ನಲ್ಲಿ ವಿನಾಯಿತಿ ಅಥವಾ ಮುಂಚಿನ ರಿಟರ್ನ್ ಸಂಭವಿಸಿದಾಗ ಈ ದೋಷದ ಸಾಮಾನ್ಯ ಮೂಲವಾಗಿದೆ. ಇದನ್ನು ತಡೆಯಲು, ಯಾವಾಗಲೂ ಸ್ವಚ್ಛಗೊಳಿಸುವಿಕೆಯನ್ನು ಖಾತರಿಪಡಿಸುವ ಭಾಷಾ ರಚನೆಗಳನ್ನು ಬಳಸಿ, ಉದಾಹರಣೆಗೆ ಜಾವಾ ಅಥವಾ C# ನಲ್ಲಿ try...finally ಬ್ಲಾಕ್ಗಳು, ಅಥವಾ C++ ನಲ್ಲಿ ಸ್ಕೋಪ್ಡ್ ಲಾಕ್ಗಳೊಂದಿಗೆ RAII (Resource Acquisition Is Initialization) ಮಾದರಿಗಳು.
ಉದಾಹರಣೆ (try-finally ಬಳಸುವ ಸೂಡೋಕೋಡ್):
my_lock.acquire();
try {
// ವಿನಾಯಿತಿಯನ್ನು ಎಸೆಯಬಹುದಾದ ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ ಕೋಡ್
} finally {
my_lock.release(); // ಇದು ಕಾರ್ಯಗತಗೊಳ್ಳುವುದು ಖಚಿತ
}
4. ಕಟ್ಟುನಿಟ್ಟಾದ ಲಾಕ್ ಕ್ರಮವನ್ನು ಅನುಸರಿಸಿ
ಡೆಡ್ಲಾಕ್ಗಳನ್ನು ತಡೆಗಟ್ಟಲು, ವೃತ್ತಾಕಾರದ ಕಾಯುವಿಕೆ ಪರಿಸ್ಥಿತಿಯನ್ನು ಮುರಿಯುವುದು ಅತ್ಯಂತ ಪರಿಣಾಮಕಾರಿ ತಂತ್ರವಾಗಿದೆ. ಬಹು ಲಾಕ್ಗಳನ್ನು ಪಡೆಯಲು ಕಟ್ಟುನಿಟ್ಟಾದ, ಜಾಗತಿಕ ಮತ್ತು ನಿರಂಕುಶವಾದ ಕ್ರಮವನ್ನು ಸ್ಥಾಪಿಸಿ. ಒಂದು ಥ್ರೆಡ್ಗೆ ಲಾಕ್ A ಮತ್ತು ಲಾಕ್ B ಎರಡನ್ನೂ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಬೇಕಾದರೆ, ಅದು ಯಾವಾಗಲೂ ಲಾಕ್ B ಅನ್ನು ಪಡೆಯುವ ಮೊದಲು ಲಾಕ್ A ಅನ್ನು ಪಡೆದುಕೊಳ್ಳಬೇಕು. ಈ ಸರಳ ನಿಯಮವು ವೃತ್ತಾಕಾರದ ಕಾಯುವಿಕೆಯನ್ನು ಅಸಾಧ್ಯವಾಗಿಸುತ್ತದೆ.
5. ಲಾಕಿಂಗ್ಗೆ ಪರ್ಯಾಯಗಳನ್ನು ಪರಿಗಣಿಸಿ
ಮೂಲಭೂತವಾಗಿದ್ದರೂ, ಲಾಕ್ಗಳು ಸಮಕಾಲೀನತೆ ನಿಯಂತ್ರಣಕ್ಕೆ ಇರುವ ಏಕೈಕ ಪರಿಹಾರವಲ್ಲ. ಹೆಚ್ಚಿನ-ಕಾರ್ಯಕ್ಷಮತೆಯ ವ್ಯವಸ್ಥೆಗಳಿಗಾಗಿ, ಸುಧಾರಿತ ತಂತ್ರಗಳನ್ನು ಅನ್ವೇಷಿಸುವುದು ಯೋಗ್ಯವಾಗಿದೆ:
- ಲಾಕ್-ಮುಕ್ತ ಡೇಟಾ ರಚನೆಗಳು: ಇವು ಕಡಿಮೆ-ಮಟ್ಟದ ಅಟಾಮಿಕ್ ಹಾರ್ಡ್ವೇರ್ ಸೂಚನೆಗಳನ್ನು (ಕಂಪೇರ್-ಅಂಡ್-ಸ್ವಾಪ್ನಂತಹ) ಬಳಸಿ ವಿನ್ಯಾಸಗೊಳಿಸಲಾದ ಅತ್ಯಾಧುನಿಕ ಡೇಟಾ ರಚನೆಗಳಾಗಿವೆ, ಇವು ಲಾಕ್ಗಳನ್ನು ಬಳಸದೆಯೇ ಸಮಕಾಲೀನ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸುತ್ತವೆ. ಇವುಗಳನ್ನು ಸರಿಯಾಗಿ ಕಾರ್ಯಗತಗೊಳಿಸುವುದು ತುಂಬಾ ಕಷ್ಟಕರ ಆದರೆ ಹೆಚ್ಚಿನ ಸ್ಪರ್ಧೆಯ ಅಡಿಯಲ್ಲಿ ಉತ್ತಮ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ನೀಡಬಲ್ಲವು.
- ಬದಲಾಗದ ಡೇಟಾ (Immutable Data): ಡೇಟಾವನ್ನು ರಚಿಸಿದ ನಂತರ ಎಂದಿಗೂ ಮಾರ್ಪಡಿಸದಿದ್ದರೆ, ಅದನ್ನು ಯಾವುದೇ ಸಿಂಕ್ರೊನೈಸೇಶನ್ನ ಅಗತ್ಯವಿಲ್ಲದೆ ಥ್ರೆಡ್ಗಳ ನಡುವೆ ಮುಕ್ತವಾಗಿ ಹಂಚಿಕೊಳ್ಳಬಹುದು. ಇದು ಫಂಕ್ಷನಲ್ ಪ್ರೋಗ್ರಾಮಿಂಗ್ನ ಒಂದು ಮೂಲ ತತ್ವವಾಗಿದೆ ಮತ್ತು ಸಮಕಾಲೀನ ವಿನ್ಯಾಸಗಳನ್ನು ಸರಳಗೊಳಿಸಲು ಹೆಚ್ಚು ಜನಪ್ರಿಯವಾಗುತ್ತಿರುವ ಮಾರ್ಗವಾಗಿದೆ.
- ಸಾಫ್ಟ್ವೇರ್ ಟ್ರಾನ್ಸಾಕ್ಷನಲ್ ಮೆಮೊರಿ (STM): ಇದು ಉನ್ನತ-ಮಟ್ಟದ ಅಬ್ಸ್ಟ್ರಾಕ್ಷನ್ ಆಗಿದ್ದು, ಡೆವಲಪರ್ಗಳಿಗೆ ಡೇಟಾಬೇಸ್ನಲ್ಲಿರುವಂತೆ ಮೆಮೊರಿಯಲ್ಲಿ ಅಟಾಮಿಕ್ ಟ್ರಾನ್ಸಾಕ್ಷನ್ಗಳನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. STM ಸಿಸ್ಟಮ್ ತೆರೆಮರೆಯಲ್ಲಿ ಸಂಕೀರ್ಣ ಸಿಂಕ್ರೊನೈಸೇಶನ್ ವಿವರಗಳನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ.
ತೀರ್ಮಾನ
ಲಾಕ್-ಆಧಾರಿತ ಸಿಂಕ್ರೊನೈಸೇಶನ್ ಸಮಕಾಲೀನ ಪ್ರೋಗ್ರಾಮಿಂಗ್ನ ಮೂಲಾಧಾರವಾಗಿದೆ. ಇದು ಹಂಚಿಕೆಯ ಸಂಪನ್ಮೂಲಗಳನ್ನು ರಕ್ಷಿಸಲು ಮತ್ತು ಡೇಟಾ ಭ್ರಷ್ಟಾಚಾರವನ್ನು ತಡೆಗಟ್ಟಲು ಶಕ್ತಿಯುತ ಮತ್ತು ನೇರವಾದ ಮಾರ್ಗವನ್ನು ಒದಗಿಸುತ್ತದೆ. ಸರಳ ಮ್ಯೂಟೆಕ್ಸ್ನಿಂದ ಹೆಚ್ಚು ಸೂಕ್ಷ್ಮವಾದ ರೀಡ್-ರೈಟ್ ಲಾಕ್ವರೆಗೆ, ಈ ಪ್ರಿಮಿಟಿವ್ಗಳು ಮಲ್ಟಿ-ಥ್ರೆಡೆಡ್ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ನಿರ್ಮಿಸುವ ಯಾವುದೇ ಡೆವಲಪರ್ಗೆ ಅಗತ್ಯವಾದ ಸಾಧನಗಳಾಗಿವೆ.
ಆದಾಗ್ಯೂ, ಈ ಶಕ್ತಿಗೆ ಜವಾಬ್ದಾರಿಯ ಅಗತ್ಯವಿದೆ. ಸಂಭಾವ್ಯ ಅಪಾಯಗಳಾದ—ಡೆಡ್ಲಾಕ್ಗಳು, ಲೈವ್ಲಾಕ್ಗಳು, ಮತ್ತು ಕಾರ್ಯಕ್ಷಮತೆಯ ಅವನತಿ—ಕುರಿತು ಆಳವಾದ ತಿಳುವಳಿಕೆ ಐಚ್ಛಿಕವಲ್ಲ. ಕ್ರಿಟಿಕಲ್ ಸೆಕ್ಷನ್ ಗಾತ್ರವನ್ನು ಕಡಿಮೆ ಮಾಡುವುದು, ಸೂಕ್ತವಾದ ಲಾಕ್ ಗ್ರ್ಯಾನ್ಯುಲಾರಿಟಿಯನ್ನು ಆಯ್ಕೆ ಮಾಡುವುದು, ಮತ್ತು ಕಟ್ಟುನಿಟ್ಟಾದ ಲಾಕ್ ಕ್ರಮವನ್ನು ಜಾರಿಗೊಳಿಸುವಂತಹ ಉತ್ತಮ ಅಭ್ಯಾಸಗಳಿಗೆ ಬದ್ಧರಾಗಿರುವ ಮೂಲಕ, ನೀವು ಸಮಕಾಲೀನತೆಯ ಶಕ್ತಿಯನ್ನು ಅದರ ಅಪಾಯಗಳನ್ನು ತಪ್ಪಿಸಿಕೊಂಡು ಬಳಸಿಕೊಳ್ಳಬಹುದು.
ಸಮಕಾಲೀನತೆಯಲ್ಲಿ ಪ್ರಾವೀಣ್ಯತೆ ಸಾಧಿಸುವುದು ಒಂದು ಪ್ರಯಾಣ. ಇದಕ್ಕೆ ಎಚ್ಚರಿಕೆಯ ವಿನ್ಯಾಸ, ಕಠಿಣ ಪರೀಕ್ಷೆ, ಮತ್ತು ಥ್ರೆಡ್ಗಳು ಸಮಾನಾಂತರವಾಗಿ ಚಲಿಸುವಾಗ ಸಂಭವಿಸಬಹುದಾದ ಸಂಕೀರ್ಣ ಸಂವಹನಗಳ ಬಗ್ಗೆ ಯಾವಾಗಲೂ ತಿಳಿದಿರುವ ಮನಸ್ಥಿತಿಯ ಅಗತ್ಯವಿದೆ. ಲಾಕಿಂಗ್ ಕಲೆಗೆ ಪ್ರಾವೀಣ್ಯತೆ ಹೊಂದುವುದರ ಮೂಲಕ, ನೀವು ವೇಗ ಮತ್ತು ಸ್ಪಂದನಾಶೀಲ ಮಾತ್ರವಲ್ಲದೆ ದೃಢ, ವಿಶ್ವಾಸಾರ್ಹ ಮತ್ತು ಸರಿಯಾದ ಸಾಫ್ಟ್ವೇರ್ ನಿರ್ಮಿಸುವತ್ತ ಒಂದು ನಿರ್ಣಾಯಕ ಹೆಜ್ಜೆಯಿಡುತ್ತೀರಿ.