๐Ÿœ์‰ฌ์šด ๋น„์œ ๋กœ ์ดํ•ดํ•˜๋Š” ์Šค๋ ˆ๋“œ์˜ ์ดํ•ด[feat. PC๋ฐฉ ์•Œ๋ฐ”์ƒ]

SUUUIยท2025๋…„ 4์›” 6์ผ

java

๋ชฉ๋ก ๋ณด๊ธฐ
15/16

โ€ผ๏ธ์˜ค๋Š˜์€ Java ์˜ ์Šค๋ ˆ๋“œ(Thread)์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์ ธ๋ณด์ž!

๐Ÿœ์–ด๋А ํ”ผ์‹œ๋ฐฉ(process)์˜ ์•Œ๋ฐ”์ƒ(Thread)๋“ค

๊ฐœ๋ฐœ์ž ์ทจ์—…์ด ์•ˆ๋ผ์„œ ํฌ๊ธฐํ•˜๊ณ  ์˜๋Œ์„ ํ•ด์„œ ํ”ผ์‹œ๋ฐฉ(Process) ์„ ์ฐจ๋ฆฐ ์œค์ˆ˜์”จ,
ํ”ผ์‹œ๋ฐฉ์˜ ์šด์˜ ๊ทœ์น™(๋ฉ”๋‰ด,๊ฐ€๊ฒฉ,์„œ๋น„์Šค ๋“ฑ๋“ฑ)(Application) ์„ ๊ตฌ์ถ•ํ•œ๋’ค
ํ”ผ์‹œ๋ฐฉ์—์„œ ์•Œ๋ฐ”๋ฅผ ํ•  ์•Œ๋ฐ”์ƒ(Thread) ๋“ค์„ ๋ฐ๋ ค์˜จ๋‹ค.

// ์•Œ๋ฐ”์ƒ(Thread) ๊ตฌํ˜„
class PCRoomWorker extends Thread {
    private String name;
    
    public PCRoomWorker(String name) {
        this.name = name;
    }
    
    @Override
    public void run() {
        System.out.println(name + " ์•Œ๋ฐ”์ƒ์ด ์ผ์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค!");
        // ์ฃผ๋ฌธ ์ฒ˜๋ฆฌ ๋กœ์ง
        System.out.println(name + " ์•Œ๋ฐ”์ƒ์ด ์ผ์„ ๋งˆ์ณค์Šต๋‹ˆ๋‹ค.");
    }
}


PCRoomWorker worker1 = new PCRoomWorker("์Šค๋ ˆ๋“œ1");
worker1.start(); // ์Šค๋ ˆ๋“œ ์‹œ์ž‘

์ž๋ฐ”์—์„œ ์Šค๋ ˆ๋“œ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ•์€ Thread ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š” ๊ฒƒ์ด๋‹ค. run() ๋ฉ”์†Œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ํ•  ์ž‘์—…์„ ์ •์˜ํ•˜๊ณ , start() ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์Šค๋ ˆ๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. ์ด๋Š” ์œค์ˆ˜์”จ์˜ ํ”ผ์‹œ๋ฐฉ์—์„œ ์•Œ๋ฐ”์ƒ์ด ์ผ์„ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.

๐ŸœThread Pool(์Šค๋ ˆ๋“œ ํ’€)

์•Œ๋ฐ”์ƒ๋“ค์„ ์†๋‹˜์˜ ์ฃผ๋ฌธ์ด ์—†์œผ๋ฉด ๋Œ€๊ธฐ์‹ค(์Šค๋ ˆ๋“œ ํ’€)์—์„œ ๋Œ€๊ธฐํ•˜๋ฉด์„œ ๊ฟ€์„ ๋นจ ์ˆ˜ ์žˆ๋‹ค(Idle ์ƒํƒœ)
์†๋‹˜์˜ ์ฃผ๋ฌธ(Request) ์ด ๋“ค์–ด์˜ค๋ฉด ์ด๊ณณ์—์„œ ํ•˜๋‚˜์˜ ์ฃผ๋ฌธ์— ๋Œ€ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ํ•œ๋ช…์˜ ์•Œ๋ฐ”์ƒ์ด ๋‚˜๊ฐ€๊ฒŒ ๋œ๋‹ค(์‹คํ–‰ ์ƒํƒœ)
๊ทธ๋ฆฌ๊ณ  ์ž‘์—…์ด ๋๋‚˜๋ฉด ๋‹ค์‹œ ๋“ค์–ด์™€์„œ ๋˜ ์ฃผ๋ฌธ์ด ๋“ค์–ด์˜ค๊ธฐ ์ „๊นŒ์ง€ ๊ฟ€์„ ๋นค๋‹ค.
ํ•˜์ง€๋งŒ ์ด ํ”ผ์‹œ๋ฐฉ์€ ์ฃผ๋ฌธ์„ ์ฒ˜๋ฆฌ ๋ชปํ–ˆ์„ ๊ฒฝ์šฐ ๋ฐ”๋กœ ์งค๋ฆฌ๊ฒŒ ๋œ๋‹ค!(์˜ˆ์™ธ ๋ฐœ์ƒ ํ›„ ์Šค๋ ˆ๋“œ ์†Œ๋ฉธ)

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class PCRoomService {
    public static void main(String[] args) {
        // 5๋ช…์˜ ์•Œ๋ฐ”์ƒ์„ ๋Œ€๊ธฐ์‹ค(์Šค๋ ˆ๋“œ ํ’€)์— ๋ฐฐ์น˜
        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        
        // ์ฃผ๋ฌธ์ด ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค ์•Œ๋ฐ”์ƒ์—๊ฒŒ ์ž‘์—… ํ• ๋‹น
        for (int i = 0; i < 10; i++) {
            final int orderNum = i;
            threadPool.execute(() -> {
                System.out.println("์•Œ๋ฐ”์ƒ #" + Thread.currentThread().getId() + 
                                 "๊ฐ€ ์ฃผ๋ฌธ #" + orderNum + "์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.");
                try {
                    Thread.sleep(1000); // ์ž‘์—… ์‹œ๊ฐ„
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("์ฃผ๋ฌธ #" + orderNum + " ์™„๋ฃŒ!");
            });
        }
        
        // ๋ชจ๋“  ์ž‘์—…์ด ๋๋‚˜๋ฉด ์Šค๋ ˆ๋“œ ํ’€ ์ข…๋ฃŒ
        threadPool.shutdown();
    }
}

ExecutorService๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์Šค๋ ˆ๋“œ ํ’€์„ ์ƒ์„ฑํ•œ๋‹ค. ์ด๋Š” ์œค์ˆ˜์”จ์˜ ํ”ผ์‹œ๋ฐฉ์—์„œ ๋Œ€๊ธฐ์‹ค์— ์•Œ๋ฐ”์ƒ๋“ค์„ ๋Œ€๊ธฐ์‹œํ‚ค๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค. ์ฃผ๋ฌธ(์ž‘์—…)์ด ๋“ค์–ด์˜ค๋ฉด ์Šค๋ ˆ๋“œ ํ’€์—์„œ ๊ฐ€์šฉํ•œ ์Šค๋ ˆ๋“œ๋ฅผ ํ• ๋‹นํ•˜์—ฌ ์ฒ˜๋ฆฌํ•˜๊ณ , ์ž‘์—…์ด ๋๋‚˜๋ฉด ์Šค๋ ˆ๋“œ๋Š” ๋‹ค์‹œ ํ’€๋กœ ๋Œ์•„๊ฐ€ ๋‹ค์Œ ์ž‘์—…์„ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ๋œ๋‹ค.

๐Ÿœ์ž„๊ณ„์˜์—ญ(Critical Section)๊ณผ ๊ฒฝ์Ÿ์ƒํƒœ(Race Condition)

์œค์ˆ˜์˜ ํ”ผ์‹œ๋ฐฉ์—๋Š” '๋ผ๋ฉด์„ ๋“์ด๋Š” ์ฃผ๋ฐฉ'์ด ์žˆ๋‹ค. ์ด ์ฃผ๋ฐฉ(์ž„๊ณ„์˜์—ญ) ์—์„œ๋Š” ํ•œ ๋ฒˆ์— ํ•œ ๋ช…์˜ ์•Œ๋ฐ”์ƒ๋งŒ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๊ณต๊ฐ„์ด ์ข์•„์„œ ๋‘ ๋ช…์ด ๋™์‹œ์— ๋“ค์–ด๊ฐ€๋ฉด ์„œ๋กœ ๋ถ€๋”ชํžˆ๊ณ  ์š”๋ฆฌ๊ฐ€ ์—‰๋ง์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค!
๊ทธ๋Ÿฌ๋˜ ์–ด๋А ๋‚ , ๋น„ ์˜ค๋Š” ์ƒˆ๋ฒฝ์— ์†๋‹˜ ๋‘ ๋ช…์ด ๋™์‹œ์— ์ฃผ๋ฌธ์„ ํ–ˆ๋‹ค

user1: "์งœํŒŒ๊ตฌ๋ฆฌ์— ๋Œ€ํŒจ์‚ผ๊ฒน์‚ด ์ถ”๊ฐ€ + ๊น€๋ฐฅ ๋ฐ˜์ค„"
user2: "์งœํŒŒ๊ตฌ๋ฆฌ์— ๋Œ€ํŒจ์‚ผ๊ฒน์‚ด ์ถ”๊ฐ€ + ์น˜์ฆˆ ๋งˆ์š” ๋ฎ๋ฐฅ"

๋‘ ๋ช…์˜ ์•Œ๋ฐ”์ƒ(Thread1, Thread2)์ด ๊ฐ๊ฐ ์ฃผ๋ฌธ์„ ๋ฐ›์•˜๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋ฌธ์ œ๋Š” ์งœํŒŒ๊ตฌ๋ฆฌ๊ฐ€ ๋”ฑ ํ•œ ์ธ๋ถ„๋งŒ ๋‚จ์•„์žˆ์—ˆ๋‹ค! ํ•˜์ง€๋งŒ ๋‘ ์•Œ๋ฐ”์ƒ ๋ชจ๋‘
"๋‚จ์•„์žˆ๋Š” ์งœํŒŒ๊ตฌ๋ฆฌ ํ™•์ธ โ†’ ์žˆ๋„ค! โ†’ ๋ผ๋ฉด ํ›„๋”ฑ ๋“์ด๊ณ  ์ˆ˜๋Ÿ‰์„ ๊ฐ์†Œ์‹œํ‚ค์ž!" ๊ณผ์ •(๋ฆฌ์†Œ์Šค ๋ณ€๊ฒฝ)
์„ ๊ฑฐ์น˜๋ ค ํ–ˆ๋‹ค.
์งœํŒŒ๊ตฌ๋ฆฌ๋ฅผ ์™„์„ฑ์‹œ์ผœ์„œ ์†๋‹˜์—๊ฒŒ ๊ฐ€์ ธ๋‹ค์ค˜์•ผ ํ•ด๊ณ ๋ฅผ ์•ˆ๋‹นํ•˜๋‹ˆ๊นŒ,
๋‘ ์•Œ๋ฐ”์ƒ์€ ๋‚ด๊ฐ€ ๋จผ์ €ํ•˜๊ฒ ๋‹ค๊ณ  *์ฃผ๋ฐฉ์•ž์—์„œ ๋ˆˆ์น˜ ์‹ธ์›€์„ ํ•˜๊ณ  ์žˆ๋‹ค(๊ฒฝ์Ÿ์ƒํƒœ(Race Condition))**
๋‘ ์•Œ๋ฐ”์ƒ์ด ๋™์‹œ์— ๊ฐ™์€ ์žฌ๋ฃŒ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์ƒํ™ฉ์ด๋‹ค(๋™์‹œ์„ฑ์ด์Šˆ).
์ด๋Ÿฐ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค:

  1. ๋‘ ์•Œ๋ฐ”์ƒ ๋ชจ๋‘ ์งœํŒŒ๊ตฌ๋ฆฌ๊ฐ€ ์žˆ๋‹ค๊ณ  ํŒ๋‹จํ•จ
  2. ์ฒซ๋ฒˆ์งธ ์•Œ๋ฐ”์ƒ(Thread1)์ด ์งœํŒŒ๊ตฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•จ
  3. ๋‘๋ฒˆ์งธ ์•Œ๋ฐ”์ƒ(Thread2) ์€ ์ด๋ฏธ ์—†์–ด์ง„ ์งœํŒŒ๊ตฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•จ
  4. ๊ฒฐ๊ตญ ๋‘๋ฒˆ์งธ ์•Œ๋ฐ”์ƒ์€ ์ฃผ๋ฌธ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๊ฒŒ ๋จ (์˜ˆ์™ธ ๋ฐœ์ƒ)
  5. ์ฃผ๋ฌธ ์ฒ˜๋ฆฌ ์‹คํŒจ๋กœ '500 ERROR' ๋ฐœ์ƒ, ์†๋‹˜์—๊ฒŒ๋Š” ์ž”๋œฉ ์š•์„ ๋จน๊ฒŒ ๋˜๊ณ  ์ฃ„์†กํ•˜๋‹ค๋Š” ๋ง๊ณผ ํ•จ๊ป˜ ๋‹ค์‹œ ์ฃผ๋ฌธํ•ด๋‹ฌ๋ผ๊ณ  ์š”์ฒญ
  6. ๊ทธ๋ฆฌ๊ณ  ๋‘๋ฒˆ์งธ ์•Œ๋ฐ”์ƒ์€ ๊ฒฐ๊ตญ ์งค๋ฆฌ๊ฒŒ ๋˜์—ˆ๋‹ค(์˜ˆ์™ธ ๋ฐœ์ƒ ํ›„ ์Šค๋ ˆ๋“œ ์†Œ๋ฉธ)
public class Kitchen {
    private int ramyeonCount = 1; // ์งœํŒŒ๊ตฌ๋ฆฌ 1๊ฐœ๋งŒ ๋‚จ์Œ
    
    // ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๋ผ๋ฉด ์ฃผ๋ฐฉ
    public boolean cookRamyeon(String workerName) {
        if (ramyeonCount > 0) {
            System.out.println(workerName + ": ์งœํŒŒ๊ตฌ๋ฆฌ๊ฐ€ " + ramyeonCount + "๊ฐœ ๋‚จ์•„์žˆ๋„ค!");
            
            // ๋ผ๋ฉด ๋“์ด๋Š”๋ฐ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค๊ณ  ๊ฐ€์ •
            try {
                Thread.sleep(1000); // ์ด ์‹œ๊ฐ„ ๋™์•ˆ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋„ ์ ‘๊ทผ ๊ฐ€๋Šฅ
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            ramyeonCount--; // ์žฌ๊ณ  ๊ฐ์†Œ
            System.out.println(workerName + ": ์งœํŒŒ๊ตฌ๋ฆฌ ์กฐ๋ฆฌ ์™„๋ฃŒ! ๋‚จ์€ ๊ฐœ์ˆ˜: " + ramyeonCount);
            return true;
        } else {
            System.out.println(workerName + ": ์งœํŒŒ๊ตฌ๋ฆฌ๊ฐ€ ์—†์–ด์š”! ์ฃผ๋ฌธ ์‹คํŒจ!");
            return false;
        }
    }
}

์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋‘ ์Šค๋ ˆ๋“œ ๋ชจ๋‘ "์งœํŒŒ๊ตฌ๋ฆฌ๊ฐ€ 1๊ฐœ ๋‚จ์•„์žˆ๋„ค!"๋ผ๊ณ  ์ถœ๋ ฅํ•˜๊ณ , ๋‘˜ ๋‹ค ๋ผ๋ฉด์„ ๋งŒ๋“œ๋Š”๋ฐ ์„ฑ๊ณตํ•˜๊ฒŒ ๋˜์–ด ์žฌ๊ณ ๊ฐ€ -1์ด ๋  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ์งœํŒŒ๊ตฌ๋ฆฌ๊ฐ€ 1๊ฐœ๋ฐ–์— ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Š” ์ž˜๋ชป๋œ ๊ฒฐ๊ณผ์ด๋‹ค.

์ธ์„ฑ์ด ๋ฐ•์‚ด๋‚œ ์œค์ˆ˜ ์‚ฌ์žฅ๋‹˜์€ ์–ด์ฐจํ”ผ ์ผํ•  ์ธ๋ ฅ์€ ๋งŽ์œผ๋‹ˆ๊นŒ,, ์งค๋ฆฐ ์ธ์› ์ˆ˜ ๋งŒํผ ๋‹ค์‹œ ๋ฐ๋ ค์™€์„œ ๋Œ€๊ธฐ์‹ค์— ์•‰ํ˜€๋†“์œผ๋ฉด ๊ทธ๋งŒ์ด๋‹ค(์Šค๋ ˆ๋“œ ํ’€์—์„œ ์†Œ๋ฉธ ๋œ ์Šค๋ ˆ๋“œ ๋งŒํผ ์žฌ์ƒ์„ฑ) ๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ณ  ๋‹ค์‹œ ์•Œ๋ฐ”์ƒ์„ ๋ฐ๋ ค์˜จ๋‹ค

๐Ÿฅฒ๊ทผ๋ฐ ๊ณ„์† ์ด๋Ÿฐ์‹์œผ๋กœ ์žฅ์‚ฌ๋ฅผ ํ•˜๋ฉด ์†๋‹˜๋“ค์ด ์—†์–ด์งˆ๊ฑฐ ๊ฐ™์•„์„œ ๋งํ• ๊ฑฐ ๊ฐ™๋‹ค๋Š” ์˜ˆ๊ฐ์ด ๋“  ์œค์ˆ˜์”จ ..

user 4 :"์—ฌ๊ธด ๋ผ๋ฉด์ด ์™œ์ผ€ ๋Šฆ๊ฒŒ ๋‚˜์™€???! 1.9ms ๋‚˜ ๊ฑธ๋ ธ์ž–์•„ !! ๋А๋ ค ํ„ฐ์กŒ๋„ค!"
(๋А๋ฆฐ ๋ผ๋ฉด ๋‚˜์˜ค๋Š” ์†๋„์— ๊ฐœ๋นก์นœ ์†๋‹˜)

user 5 : "ํ’ˆ์ ˆ ์ฒ˜๋ฆฌ๋ฅผ ๋นจ๋ฆฌ ํ–ˆ์—ˆ์–ด์•ผ ์ฃผ๋ฌธ์„ ์•ˆํ•˜์ง€!! ์žฅ์‚ฌ ์ด๋”ฐ๊ตฌ๋กœ ํ• ๊ฑฐ์•ผ??!"
(์ •ํ™•ํ•œ ์ •๋ณด๋ฅผ ์ฃผ์ง€ ์•Š์•„ ๊ฐœ๋นก์นœ ์†๋‹˜)

๊ฒฐ๊ตญ ์œค์ˆ˜์”จ๋Š” ์ด๋Ÿฐ ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ๊ฐ€์ง€ ํ•ด๊ฒฐ๋ฐฉ์•ˆ์„ ๊ณ ๋ฏผํ•˜๊ฒŒ ๋๋‹ค(ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…์— ๋Œ€์‘) !

์œค์ˆ˜์”จ : "๊ฐœ๋ฐœ ์ทจ์—…๋„ ์•ˆ๋๋Š”๋ฐ .. ํ”ผ์‹œ๋ฐฉ ์šด์˜ ์ž˜ํ•ด์„œ ๋นš์„ ๋นจ๋ฆฌ ๊ฐš์•„์•ผ์ง€ .. ํ‘ํ‘"

๊ณผ์—ฐ ์œค์ˆ˜์”จ๋Š” ์–ด๋–ป๊ฒŒ ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ?
๐Ÿœ๋‹ค์ŒํŽธ์—์„œ ๊ณ„์†

profile
๊ฐ„๋‹จํ•œ ๊ฐœ๋ฐœ ๊ธฐ๋ก

0๊ฐœ์˜ ๋Œ“๊ธ€