ããã¯ãããããã¯æ€åºåšã䜿çšããŠãããã³ããšã³ãWebã¢ããªã±ãŒã·ã§ã³ã§ã®ãããããã¯ã鲿¢ã»æ€åºããæ¹æ³ãåŠã³ãŸããããã¹ã ãŒãºãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãšå¹ççãªãªãœãŒã¹ç®¡çãå®çŸããŸãã
ããã³ããšã³ãWebããã¯ãããããã¯æ€åºåšïŒãªãœãŒã¹ç«¶åã®é²æ¢
çŸä»£ã®Webã¢ããªã±ãŒã·ã§ã³ãç¹ã«è€éãªJavaScriptãã¬ãŒã ã¯ãŒã¯ãšéåææäœã§æ§ç¯ãããã¢ããªã±ãŒã·ã§ã³ã§ã¯ãå ±æãªãœãŒã¹ã广çã«ç®¡çããããšãéèŠã§ããæœåšçãªèœãšã穎ã®1ã€ã¯ããããããã¯ã®çºçã§ããããã¯ã2ã€ä»¥äžã®ããã»ã¹ïŒãã®å Žåã¯JavaScriptã³ãŒããããã¯ïŒããäºãããªãœãŒã¹ãè§£æŸããã®ãåŸ ã£ãŠç¡æéã«ãããã¯ãããç¶æ³ã§ããããã«ãããã¢ããªã±ãŒã·ã§ã³ã®å¿ç忢ããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã®äœäžã蚺æãå°é£ãªãã°ãçºçããå¯èœæ§ããããŸããããã³ããšã³ãWebããã¯ãããããã¯æ€åºåšãå®è£ ããããšã¯ããã®ãããªåé¡ãç¹å®ãã鲿¢ããããã®ç©æ¥µçãªæŠç¥ã§ãã
ãããããã¯ã®çè§£
ãããããã¯ã¯ãäžé£ã®ããã»ã¹ããã¹ãŠãããã¯ãããŠãããšãã«çºçããŸããåããã»ã¹ããªãœãŒã¹ãä¿æããå¥ã®ããã»ã¹ãä¿æããŠãããªãœãŒã¹ã®ååŸãåŸ æ©ããŠããããã§ããããã«ãã埪ç°çãªäŸåé¢ä¿ãçãŸããã©ã®ããã»ã¹ãé²è¡ã§ããªããªããŸãã
ãããããã¯ã®å¿ èŠæ¡ä»¶
éåžžããããããã¯ãçºçããã«ã¯ã以äžã®4ã€ã®æ¡ä»¶ãåæã«ååšããå¿ èŠããããŸãã
- çžäºæä»: ãªãœãŒã¹ã¯è€æ°ã®ããã»ã¹ã«ãã£ãŠåæã«äœ¿çšããããšã¯ã§ããŸãããäžåºŠã«1ã€ã®ããã»ã¹ã®ã¿ããªãœãŒã¹ãä¿æã§ããŸãã
- ä¿æãšåŸ æ©: ããããã»ã¹ãå°ãªããšã1ã€ã®ãªãœãŒã¹ãä¿æããä»ã®ããã»ã¹ãä¿æããŠãã远å ã®ãªãœãŒã¹ã®ååŸãåŸ æ©ããŠããŸãã
- éå²ã蟌ã¿: ãªãœãŒã¹ã¯ããããä¿æããŠããããã»ã¹ãã匷å¶çã«å¥ªãåãããšã¯ã§ããŸããããªãœãŒã¹ã¯ããããä¿æããŠããããã»ã¹ã«ãã£ãŠã®ã¿èªçºçã«è§£æŸãããŸãã
- 埪ç°åŸ æ©: ããã»ã¹ã®åŸªç°çãªé£éãååšããåããã»ã¹ãé£éå ã®æ¬¡ã®ããã»ã¹ãä¿æããŠãããªãœãŒã¹ãåŸ æ©ããŠããŸãã
ããã4ã€ã®æ¡ä»¶ãã¹ãŠãæºããããå Žåããããããã¯ãçºçããå¯èœæ§ããããŸãããããã®æ¡ä»¶ã®ãããã1ã€ãåé€ãŸãã¯é²æ¢ããããšã§ããããããã¯ãé²ãããšãã§ããŸãã
ããã³ããšã³ãWebã¢ããªã±ãŒã·ã§ã³ã«ããããããããã¯
ãããããã¯ã¯ããã¯ãšã³ãã·ã¹ãã ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®æèã§ããäžè¬çã«è°è«ãããŸãããç¹ã«ä»¥äžã®ãããªè€éãªã·ããªãªã§ã¯ãããã³ããšã³ãWebã¢ããªã±ãŒã·ã§ã³ã§ãçºçããå¯èœæ§ããããŸãã
- éåææäœ: JavaScriptã®éåææ§ïŒäŸ: `async/await`ã`Promise.all`ã`setTimeout`ã®äœ¿çšïŒã¯ãè€æ°ã®ã³ãŒããããã¯ãäºãã®å®äºãåŸ ã€ãããªè€éãªå®è¡ãããŒãäœãåºãå¯èœæ§ããããŸãã
- å ±æã¹ããŒã管ç: ReactãAngularãVue.jsãªã©ã®ãã¬ãŒã ã¯ãŒã¯ã¯ãã³ã³ããŒãã³ãéã§å ±æã¹ããŒãã管çããããšããããããŸãããã®ã¹ããŒããžã®åæã¢ã¯ã»ã¹ã¯ãé©åã«åæãããŠããªãå Žåãç«¶åç¶æ ããããããã¯ã«ã€ãªããå¯èœæ§ããããŸãã
- ãµãŒãããŒãã£ã©ã€ãã©ãª: å éšã§ãªãœãŒã¹ã管çããã©ã€ãã©ãªïŒäŸ: ãã£ãã·ã³ã°ã©ã€ãã©ãªãã¢ãã¡ãŒã·ã§ã³ã©ã€ãã©ãªïŒã¯ããããããã¯ã®äžå ãšãªãããã¯ã¡ã«ããºã ã䜿çšããå ŽåããããŸãã
- Web Workers: ããã¯ã°ã©ãŠã³ãã¿ã¹ã¯ã«Web Workersãå©çšãããšã䞊ååŠçãå°å ¥ãããã¡ã€ã³ã¹ã¬ãããšã¯ãŒã«ãŒéã®ãªãœãŒã¹ç«¶åã®å¯èœæ§ãçããŸãã
äŸç€ºã·ããªãªïŒåçŽãªãªãœãŒã¹ç«¶å
2ã€ã®éåæé¢æ° `resourceA` ãš `resourceB` ãèããŠã¿ãŸããããããããã2ã€ã®æ¶ç©ºã®ãã㯠`lockA` ãš `lockB` ãååŸããããšããŸãã
```javascript async function resourceA() { await lockA.acquire(); try { await lockB.acquire(); // Perform operation requiring both lockA and lockB } finally { lockB.release(); lockA.release(); } } async function resourceB() { await lockB.acquire(); try { await lockA.acquire(); // Perform operation requiring both lockA and lockB } finally { lockA.release(); lockB.release(); } } // Concurrent execution resourceA(); resourceB(); ```ãã `resourceA` ã `lockA` ãååŸããåæã« `resourceB` ã `lockB` ãååŸããå Žåãäž¡æ¹ã®é¢æ°ã¯ãããäžæ¹ãå¿ èŠãªããã¯ãè§£æŸããã®ãåŸ ã£ãŠãç¡æéã«ãããã¯ãããŸããããã¯å€å žçãªãããããã¯ã®ã·ããªãªã§ãã
ããã³ããšã³ãWebããã¯ãããããã¯æ€åºåšïŒæŠå¿µãšå®è£
ããã³ããšã³ãWebããã¯ãããããã¯æ€åºåšã¯ã以äžã®æ¹æ³ã§ãããããã¯ãç¹å®ããæœåšçã«é²æ¢ããããšãç®çãšããŠããŸãã
- ããã¯ååŸã®è¿œè·¡: ããã¯ããã€ååŸããããã€è§£æŸãããããç£èŠããŸãã
- 埪ç°äŸåã®æ€åº: ããã»ã¹ãäºãã«åŸªç°çã«åŸ æ©ããŠããç¶æ³ãç¹å®ããŸãã
- èšºææ å ±ã®æäŸ: ãããã°ã«åœ¹ç«ã€ãããã¯ã®ç¶æ ãšãããåŸ æ©ããŠããããã»ã¹ã«é¢ããæ å ±ãæäŸããŸãã
å®è£ ã¢ãããŒã
ããã³ããšã³ãWebã¢ããªã±ãŒã·ã§ã³ã§ãããããã¯æ€åºåšãå®è£ ããã«ã¯ãããã€ãã®æ¹æ³ããããŸãã
- ãããããã¯æ€åºæ©èœä»ãã«ã¹ã¿ã ããã¯ç®¡ç: ãããããã¯æ€åºããžãã¯ãå«ãã«ã¹ã¿ã ããã¯ç®¡çã·ã¹ãã ãå®è£ ããŸãã
- æ¢åã©ã€ãã©ãªã®äœ¿çš: ããã¯ç®¡çããã³ãããããã¯æ€åºæ©èœãæäŸããæ¢åã®JavaScriptã©ã€ãã©ãªã調æ»ããŸãã
- èšè£ ãšç£èŠ: ããã¯ã®ååŸããã³è§£æŸã€ãã³ãã远跡ããããã«ã³ãŒããèšè£ ããæœåšçãªãããããã¯ã«ã€ããŠãããã®ã€ãã³ããç£èŠããŸãã
ãããããã¯æ€åºæ©èœä»ãã«ã¹ã¿ã ããã¯ç®¡ç
ãã®ã¢ãããŒãã§ã¯ãç¬èªã®ããã¯ãªããžã§ã¯ããäœæããããã¯ã®ååŸãè§£æŸããããããã¯ã®æ€åºã«å¿ èŠãªããžãã¯ãå®è£ ããŸãã
åºæ¬çãªããã¯ã¯ã©ã¹
```javascript class Lock { constructor() { this.locked = false; this.waiting = []; } acquire() { return new Promise((resolve) => { if (!this.locked) { this.locked = true; resolve(); } else { this.waiting.push(resolve); } }); } release() { if (this.waiting.length > 0) { const next = this.waiting.shift(); next(); } else { this.locked = false; } } } ```ãããããã¯æ€åº
ãããããã¯ãæ€åºããã«ã¯ãã©ã®ããã»ã¹ïŒäŸ: éåæé¢æ°ïŒãã©ã®ããã¯ãä¿æããã©ã®ããã¯ãåŸ æ©ããŠãããã远跡ããå¿ èŠããããŸãããã®æ å ±ã衚ãããã«ã°ã©ãããŒã¿æ§é ã䜿çšã§ããŸããããã§ããŒãã¯ããã»ã¹ã衚ãããšããžã¯äŸåé¢ä¿ïŒã€ãŸããããããã»ã¹ãå¥ã®ããã»ã¹ã«ãã£ãŠä¿æãããŠããããã¯ãåŸ æ©ããŠããïŒã衚ããŸãã
```javascript class DeadlockDetector { constructor() { this.graph = new Map(); // Process -> Set of Locks Waiting For this.lockHolders = new Map(); // Lock -> Process this.processIdCounter = 0; this.processContext = new Map(); // processId -> { locksHeld: Set`DeadlockDetector` ã¯ã©ã¹ã¯ãããã»ã¹ãšããã¯éã®äŸåé¢ä¿ã衚ãã°ã©ããç¶æããŸãã`detectDeadlock` ã¡ãœããã¯ãæ·±ãåªå æ¢çŽ¢ã¢ã«ãŽãªãºã ã䜿çšããŠã°ã©ãå ã®ãµã€ã¯ã«ïŒãããããã¯ã瀺ãïŒãæ€åºããŸãã
ããã¯ååŸãšãããããã¯æ€åºã®çµ±å
`Lock` ã¯ã©ã¹ã® `acquire` ã¡ãœãããä¿®æ£ããããã¯ãä»äžããåã«ãããããã¯æ€åºããžãã¯ãåŒã³åºãããã«ããŸãããããããã¯ãæ€åºãããå Žåã¯ãäŸå€ãã¹ããŒãããããšã©ãŒããã°ã«èšé²ããŸãã
```javascript const lockA = new SafeLock(); const lockB = new SafeLock(); async function resourceA() { const { processId, release } = await lockA.acquire(); try { const { processId: processIdB, release: releaseB } = await lockB.acquire(); try { // Critical Section using A and B console.log("Resource A and B acquired in resourceA"); } finally { releaseB(); } } finally { release(); } } async function resourceB() { const { processId, release } = await lockB.acquire(); try { const { processId: processIdA, release: releaseA } = await lockA.acquire(); try { // Critical Section using A and B console.log("Resource A and B acquired in resourceB"); } finally { releaseA(); } } finally { release(); } } async function testDeadlock() { try { await Promise.all([resourceA(), resourceB()]); } catch (error) { console.error("Error during deadlock test:", error); } } // Call the test function testDeadlock(); ```æ¢åã©ã€ãã©ãªã®äœ¿çš
ããã€ãã®JavaScriptã©ã€ãã©ãªã¯ãããã¯ç®¡çãšäžŠè¡æ§å¶åŸ¡ã¡ã«ããºã ãæäŸããŸãããããã®ã©ã€ãã©ãªã®äžéšã«ã¯ããããããã¯æ€åºæ©èœãå«ãŸããŠããããããããåã蟌ãããã«æ¡åŒµã§ããå ŽåããããŸããããã€ãã®äŸãæããŸãã
- `async-mutex`: éåæJavaScriptçšã®ãã¥ãŒããã¯ã¹å®è£ ãæäŸããŸããããã«ãããããã¯æ€åºããžãã¯ã远å ã§ããå¯èœæ§ããããŸãã
- `p-queue`: 䞊è¡ã¿ã¹ã¯ã管çãããªãœãŒã¹ã¢ã¯ã»ã¹ãå¶éããããã«äœ¿çšã§ããåªå 床ãã¥ãŒã§ãã
æ¢åã®ã©ã€ãã©ãªã䜿çšãããšãããã¯ç®¡çã®å®è£ ãç°¡çŽ åã§ããŸãããã©ã€ãã©ãªã®æ©èœãšããã©ãŒãã³ã¹ç¹æ§ãã¢ããªã±ãŒã·ã§ã³ã®ããŒãºãæºãããŠããããšã確èªããããã«ãæ éãªè©äŸ¡ãå¿ èŠã§ãã
èšè£ ãšç£èŠ
ãã1ã€ã®ã¢ãããŒãã¯ãããã¯ã®ååŸããã³è§£æŸã€ãã³ãã远跡ããããã«ã³ãŒããèšè£ ããæœåšçãªãããããã¯ã«ã€ããŠãããã®ã€ãã³ããç£èŠããããšã§ããããã¯ããã®ã³ã°ãã«ã¹ã¿ã ã€ãã³ãããŸãã¯ããã©ãŒãã³ã¹ç£èŠããŒã«ã䜿çšããŠå®çŸã§ããŸãã
ãã®ã³ã°
ããã¯ã®ååŸããã³è§£æŸã¡ãœããã«ãã®ã³ã°ã¹ããŒãã¡ã³ãã远å ããŠããã€ããã¯ãååŸãããè§£æŸããããããããŠã©ã®ããã»ã¹ãããããåŸ æ©ããŠããããèšé²ããŸãããã®æ å ±ãåæããŠãæœåšçãªãããããã¯ãç¹å®ã§ããŸãã
ã«ã¹ã¿ã ã€ãã³ã
ããã¯ãååŸãŸãã¯è§£æŸããããšãã«ã«ã¹ã¿ã ã€ãã³ãããã£ã¹ãããããŸãããããã®ã€ãã³ãã¯ãç£èŠããŒã«ãŸãã¯ã«ã¹ã¿ã ã€ãã³ããã³ãã©ã«ãã£ãŠãã£ããã£ãããããã¯ã®äœ¿çšç¶æ³ã远跡ãããããããã¯ãæ€åºã§ããŸãã
ããã©ãŒãã³ã¹ç£èŠããŒã«
ã¢ããªã±ãŒã·ã§ã³ãããã©ãŒãã³ã¹ç£èŠããŒã«ãšçµ±åãããªãœãŒã¹äœ¿çšéã远跡ããæœåšçãªããã«ããã¯ãç¹å®ã§ããããã«ããŸãããããã®ããŒã«ã¯ãããã¯ç«¶åãšãããããã¯ã«é¢ããæŽå¯ãæäŸããå ŽåããããŸãã
ãããããã¯ã®é²æ¢
ãããããã¯ã®æ€åºã¯éèŠã§ããããããããããããã¯ãçºçããªãããã«ããããšãããã«åªããŠããŸããããã³ããšã³ãWebã¢ããªã±ãŒã·ã§ã³ã§ãããããã¯ã鲿¢ããããã®æŠç¥ãããã€ã玹ä»ããŸãã
- ããã¯é åºä»ã: ããã¯ãååŸãããäžè²«ããé åºã確ç«ããŸãããã¹ãŠã®ããã»ã¹ãåãé åºã§ããã¯ãååŸããå Žåã埪ç°åŸ æ©æ¡ä»¶ã¯çºçããŸããã
- ããã¯ã¿ã€ã ã¢ãŠã: ããã¯ååŸã®ããã®ã¿ã€ã ã¢ãŠãã¡ã«ããºã ãå®è£ ããŸããããã»ã¹ãäžå®æéå ã«ããã¯ãååŸã§ããªãå ŽåãçŸåšä¿æããŠãããã¹ãŠã®ããã¯ãè§£æŸããåŸã§å詊è¡ããŸããããã«ãããããã»ã¹ãç¡æéã«ãããã¯ãããã®ãé²ããŸãã
- ãªãœãŒã¹éå±€: ãªãœãŒã¹ãéå±€çã«æŽçããããã»ã¹ãäžäœããäžäœã®é åºã§ãªãœãŒã¹ãååŸããããã«èŠæ±ããŸããããã«ããã埪ç°äŸåãé²ãããšãã§ããŸãã
- ãã¹ããããããã¯ã®åé¿: ãã¹ããããããã¯ã®äœ¿çšãæå°éã«æããŸããããã«ãããããããã¯ã®ãªã¹ã¯ãå¢å ããããã§ãããã¹ããããããã¯ãå¿ èŠãªå Žåã¯ãå€åŽã®ããã¯ã®åã«å åŽã®ããã¯ãè§£æŸãããããã«ããŸãã
- éããããã³ã°æäœã®äœ¿çš: å¯èœãªéãéããããã³ã°æäœãåªå ããŸããéããããã³ã°æäœã¯ããªãœãŒã¹ãããã«å©çšã§ããªãå Žåã§ãããã»ã¹ãå®è¡ãç¶ç¶ã§ããããã«ããããããããããã¯ã®å¯èœæ§ãäœæžããŸãã
- 培åºçãªãã¹ã: æœåšçãªãããããã¯ãç¹å®ããããã«åŸ¹åºçãªãã¹ãã宿œããŸããäžŠè¡æ§ãã¹ãããŒã«ãšæè¡ã䜿çšããŠãå ±æãªãœãŒã¹ãžã®åæã¢ã¯ã»ã¹ãã·ãã¥ã¬ãŒããããããããã¯æ¡ä»¶ãæããã«ããŸãã
äŸïŒããã¯é åºä»ã
åã®äŸã䜿çšããŠãäž¡æ¹ã®é¢æ°ãåãé åºã§ããã¯ãååŸããããã«ããããšã§ïŒäŸ: åžžã« `lockB` ã®åã« `lockA` ãååŸããïŒããããããã¯ãåé¿ã§ããŸãã
```javascript async function resourceA() { const { processId, release } = await lockA.acquire(); try { const { processId: processIdB, release: releaseB } = await lockB.acquire(); try { // Critical Section using A and B console.log("Resource A and B acquired in resourceA"); } finally { releaseB(); } } finally { release(); } } async function resourceB() { const { processId, release } = await lockA.acquire(); // Acquire lockA first try { const { processId: processIdB, release: releaseB } = await lockB.acquire(); try { // Critical Section using A and B console.log("Resource A and B acquired in resourceB"); } finally { releaseB(); } } finally { release(); } } async function testDeadlock() { try { await Promise.all([resourceA(), resourceB()]); } catch (error) { console.error("Error during deadlock test:", error); } } // Call the test function testDeadlock(); ```åžžã« `lockB` ã®åã« `lockA` ãååŸããããã«ããããšã§ã埪ç°åŸ æ©æ¡ä»¶ãæé€ãããããããã¯ãé²ããŸãã
çµè«
ãããããã¯ã¯ãéåææäœãå ±æã¹ããŒã管çããµãŒãããŒãã£ã©ã€ãã©ãªãå«ãè€éãªã·ããªãªã«ãããŠãããã³ããšã³ãWebã¢ããªã±ãŒã·ã§ã³ã§é倧ãªèª²é¡ãšãªãå¯èœæ§ããããŸããã¹ã ãŒãºãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãå¹ççãªãªãœãŒã¹ç®¡çãããã³ã¢ããªã±ãŒã·ã§ã³ã®å®å®æ§ã確ä¿ããããã«ã¯ãããã³ããšã³ãWebããã¯ãããããã¯æ€åºåšãå®è£ ãããããããã¯é²æ¢æŠç¥ãæ¡çšããããšãäžå¯æ¬ ã§ãããããããã¯ã®åå ãçè§£ããé©åãªæ€åºã¡ã«ããºã ãå®è£ ãã鲿¢æè¡ãæ¡çšããããšã§ãããå ç¢ã§ä¿¡é Œæ§ã®é«ãããã³ããšã³ãã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸãã
ã¢ããªã±ãŒã·ã§ã³ã®ããŒãºãšè€éãã«æé©ãªå®è£ ã¢ãããŒããéžæããããšãå¿ããªãã§ãã ãããã«ã¹ã¿ã ããã¯ç®¡çã¯æãå€ãã®å¶åŸ¡ãæäŸããŸãããããå€ãã®åŽåãå¿ èŠã§ããæ¢åã®ã©ã€ãã©ãªã¯ããã»ã¹ãç°¡çŽ åã§ããŸãããå¶éãããå ŽåããããŸããèšè£ ãšç£èŠã¯ãã³ã¢ã®ããã¯ããžãã¯ã倿Žããããšãªããããã¯ã®äœ¿çšç¶æ³ã远跡ãããããããã¯ãæ€åºããããã®æè»ãªæ¹æ³ãæäŸããŸããã©ã®æ¹æ³ãéžæããã«ããŠããæç¢ºãªããã¯ååŸãããã³ã«ã確ç«ãããªãœãŒã¹ã®ç«¶åãæå°éã«æããããšã§ããããããã¯ã®é²æ¢ãåªå ããŠãã ããã