9 ๋ถ„ ์†Œ์š”

1. ์Šค๋ ˆ๋“œ์˜ ๊ฐœ๋…

์šด์˜์ฒด์ œ - ํ”„๋กœ์„ธ์Šค์˜ ๊ฐœ๋… ๋„์‹

์ •์ ์ธ ํ”„๋กœ๊ทธ๋žจ์ด ์ž์›(CPU๋‚˜ ๋ฉ”๋ชจ๋ฆฌ)์„ ์–ป์–ด ์‹คํ–‰ ์ค‘์— ๋“ค์–ด๊ฐ„ ๊ฒƒ์„ ํ”„๋กœ์„ธ์Šค๋ผ ํ•˜๋ฉฐ, ๋ชจ๋“  ํ”„๋กœ๊ทธ๋žจ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ”„๋กœ์„ธ์Šค ๋‹จ์œ„๋กœ ์‹คํ–‰๋œ๋‹ค. ์Šค๋ ˆ๋“œ๋Š” ํ”„๋กœ์„ธ์Šค ๋‚ด์˜ ์ž‘์€ ์‹คํ–‰ ๋‹จ์œ„์ด๋ฉฐ ํ”„๋กœ์„ธ์Šค๋Š” ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋กœ ๊ตฌ์„ฑ๋˜๊ฑฐ๋‚˜ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž‘์€ ์Šค๋ ˆ๋“œ๋กœ ๊ตฌ์„ฑ๋  ์ˆ˜ ์žˆ๋‹ค.

JAVA ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰์‹œํ‚ค๋ฉด JVM ์ƒ์— ์ž๋™์œผ๋กœ ์Šค๋ ˆ๋“œ๊ฐ€ ํ•˜๋‚˜ ์ƒ์„ฑ๋˜๊ณ  ์ด๋ฅผ โ€˜๋ฉ”์ธ ์Šค๋ ˆ๋“œโ€™ ๋ผ ํ•œ๋‹ค. ๋ฉ”์ธ ์Šค๋ ˆ๋“œ ๋‚ด์—์„œ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ณ , ๋ชจ๋“  ์Šค๋ ˆ๋“œ๋Š” ์šฐ์„ ์ˆœ์œ„(priority)๋ฅผ ๊ฐ€์ง€๋Š”๋ฐ, ์ฒ˜์Œ์—๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ž์‹ ์„ ์ƒ์„ฑํ•œ ์Šค๋ ˆ๋“œ์™€ ๋™์ผํ•œ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง€๊ณ  ์ƒ์„ฑ๋œ๋‹ค. ๊ฐ ์Šค๋ ˆ๋“œ ๋ณ„ ์šฐ์„ ์ˆœ์œ„๋ฅผ ์ž„์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์ด๋•Œ ์Šค๋ ˆ๋“œ๋ฅผ ์ถ”์ƒํ™” ํ•œ Thread ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•œ๋‹ค.

2. ์Šค๋ ˆ๋“œ ํด๋ž˜์Šค

๋‹ค์Œ์€ ์ž๋ฐ” ์Šค๋ ˆ๋“œ ํด๋ž˜์Šค ๋‚ด๋ถ€์˜ ์ฃผ์š” ์ƒ์ˆ˜์™€ ์ƒ์„ฑ์ž, ๊ทธ๋ฆฌ๊ณ  ๋ฉ”์„œ๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž.

2-1. ์ฃผ์š” ์ƒ์ˆ˜

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* ์Šค๋ ˆ๋“œ์˜ ๋ฐ๋ชฌ ์—ฌ๋ถ€ */
private boolean daemon = false;

/* ์Šค๋ ˆ๋“œ์˜ ์ƒํƒœ */
private volatile int threadStatus;

/* ์Šค๋ ˆ๋“œ ์šฐ์„ ์ˆœ์œ„ ์ตœ์†Œ๊ฐ’ */
public static final int MIN_PRIORITY = 1;

/* ์Šค๋ ˆ๋“œ ์šฐ์„ ์ˆœ์œ„ ๊ธฐ๋ณธ๊ฐ’ */
public static final int NORM_PRIORITY = 5;

/* ์Šค๋ ˆ๋“œ ์šฐ์„ ์ˆœ์œ„ ์ตœ๋Œ€๊ฐ’ */
public static final int MAX_PRIORITY = 10;

2-2. ์ฃผ์š” ์ƒ์„ฑ์ž

1
2
3
4
5
6
7
8
/**
* 1. ์Šค๋ ˆ๋“œ ๊ทธ๋ฃน
* 2. Runnable Interface ๋ฅผ ์ƒ์†๋ฐ›๋Š” ์‹คํ–‰ ๋Œ€์ƒ
* 3. ์Šค๋ ˆ๋“œ ๋„ค์ž„ (๊ธฐ๋ณธ ๊ฐ’์œผ๋กœ "Thread-" + nextThreadNum() ํ˜•์‹์„ ๊ฐ€์ง„๋‹ค
*/
public Thread(ThreadGroup group, Runnable target, String name) {
    this(group, target, name, 0);
}

2-3. ์ฃผ์š” ๋ฉ”์„œ๋“œ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//ํ˜„์žฌ ์‹คํ–‰์ค‘์ธ ์Šค๋ ˆ๋“œ๊ฐ€ this ์Šค๋ ˆ๋“œ๋ฅผ ์ œ์–ดํ•  ๊ถŒํ•œ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
//์—†๋‹ค๋ฉด SecurityException ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
public final void checkAccess() {...}

//this ์Šค๋ ˆ๋“œ์˜ ์šฐ์„ ์ˆœ์œ„๋ฅผ ์„ค์ •ํ•œ๋‹ค.
public final void setPriority(int newPriority) {...}

//์‹คํ–‰ ์ค‘๋‹จ์ƒํƒœ์— ์žˆ๋Š” this ์Šค๋ ˆ๋“œ๋ฅผ ๊นจ์šด๋‹ค.
public void interrupt() {...}

//this ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ฑฐ๋‚˜ ์ง€์ •๋œ ์‹œ๊ฐ„(milllis) ๋งŒํผ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
public final synchronized void join() throws InterreptedException {...}
public final synchronized void join(long millis) throws InterreptedException {...}

//ํ˜„์žฌ ์‹คํ–‰์ค‘์ธ ์Šค๋ ˆ๋“œ๋ฅผ ์ผ์‹œ์ ์œผ๋กœ ๋ฉˆ์ถ”๊ฒŒ ํ•ด์„œ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ํ•œ๋‹ค.
public static void yeild() {...} 

//ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ ์ง€์ •๋œ ์‹œ๊ฐ„(millis) ๋งŒํผ ์‹คํ–‰์„ ๋ฉˆ์ถ˜๋‹ค. 
public static void sleep(long millis) {...}

2-4. Object ํด๋ž˜์Šค์˜ ์Šค๋ ˆ๋“œ ๊ด€๋ จ ์ฃผ์š” ๋ฉ”์„œ๋“œ

1
2
3
4
5
6
7
//ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ notify() ํ˜น์€ notifyAll() ์„ ํ˜ธ์ถœํ• ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ์‹œํ‚จ๋‹ค.
public final native void wait() throws InterruptedException;
public final native void wait(long timeoutMillis) throws InterruptedException;

//๋Œ€๊ธฐ์ค‘์ธ ์Šค๋ ˆ๋“œ๋ฅผ ํ•˜๋‚˜ ํ˜น์€ ๋ชจ๋‘ ๊นจ์šด๋‹ค.
public final native void notify();
public final native void notifyAll();

3. ์Šค๋ ˆ๋“œ์˜ ์ƒ์„ฑ

์Šค๋ ˆ๋“œ์˜ ์ƒ์„ฑ์—๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. Thread ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๊ฑฐ๋‚˜ Runnable ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด๋กœ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. JAVA๋Š” ๋‹ค์ค‘์ƒ์†์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ๋‹ค๋ฅธ ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์œผ๋ฉด์„œ ์Šค๋ ˆ๋“œ๋กœ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Runnable ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

3-1. Thread ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๊ธฐ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Scratch {

    public static void main(String[] args)  {

        MyThread thread = new MyThread();
        // 3.start() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์‹คํ–‰ํ•œ๋‹ค.
        thread.start();
    }	
}

//1. Thread ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š” ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•œ๋‹ค.
class MyThread extends Thread {

    // 2. run() ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•œ๋‹ค.
    @Override
    public void run() {

        for (int i = 0; i < 10; i++) {
            System.out.println("[" + this.getName() + "]i = " + i);
        }
    }
}

3-2. Runnable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Scratch {

    public static void main(String[] args)  {

        // 3.Runnable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›์€ ์ธ์Šคํ„ด์Šค๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ Thread ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค
        Thread thread = new Thread(new MyThread());
        // 4.start() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์‹คํ–‰ํ•œ๋‹ค.
        thread.start();
    }
}

//1. Runnable ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด๋กœ ์ƒ์„ฑํ•œ๋‹ค.
class MyThread implements Runnable {

    // 2. run() ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•œ๋‹ค.
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("i = " + i);
        }
    }
}
1๋ฒˆ๊ณผ 2๋ฒˆ์— ๋Œ€ํ•œ ์‹คํ–‰ ๊ฒฐ๊ณผ

3-EX. Thread ๋ฉ”์„œ๋“œ์˜ start() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์‹คํ–‰์‹œ์ผœ์•ผ ํ•˜๋Š” ์ด์œ 

Runnable ์ธํ„ฐํŽ˜์ด์Šค์˜ run() ๋ฉ”์„œ๋“œ๋ฅผ ์ง์ ‘ ์‹คํ–‰์‹œํ‚ค์ง€ ์•Š๋Š” ์ด์œ ๋Š” Thread ๊ฐ์ฒด์˜ start() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ๋งŒ JVM์ด ์ƒˆ๋กœ์šด ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  run() ๋ฉ”์„œ๋“œ ์˜์—ญ์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ทธ๋ƒฅ run() ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚จ๋‹ค๋ฉด ์ƒˆ๋กœ์šด ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ ์˜์—ญ์—์„œ run() ๋ฉ”์„œ๋“œ์˜ ๋‚ด์šฉ๋งŒ์„ ์‹คํ–‰์‹œํ‚จ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Scratch {

    public static void main(String[] args)  {

        MyThread thread1 = new MyThread();
        thread1.run();

        MyThread thread2 = new MyThread();
        thread2.run();

        System.out.println("===== main end =====");
    }
}

class MyThread implements Runnable {

    @Override
    public void run() {
        for (int i = 1; i <= 3; i++) {
            System.out.println("[" + Thread.currentThread().getName() + "] i = " + i);
        }
    }
}
๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์ง€ ์•Š๊ณ  ๋ฉ”์ธ์Šค๋ ˆ๋“œ์—์„œ ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰๋˜๊ณ  ์žˆ๋‹ค.

4. ์Šค๋ ˆ๋“œ์˜ ์ƒํƒœ

๋‹ค์Œ์€ ์Šค๋ ˆ๋“œ๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  CPU์˜ ์ž์›์„ ์–ป์–ด ์‹คํ–‰ ๋œ ํ›„, ์ข…๋ฃŒ ์ƒํƒœ์— ์ด๋ฅด๊ธฐ๊นŒ์ง€ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ๋“ค์ด๋‹ค.

4-1. Startable ์ƒํƒœ

Thread ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ์ƒํƒœ์ด๋‹ค. ์ฆ‰, start() ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ๋ฐ”๋กœ ์ง์ „์˜ ์ƒํƒœ์ด๋‹ค. ๋ชจ๋“  ์Šค๋ ˆ๋“œ๋Š” Startable ์ƒํƒœ์—์„œ๋งŒ Runnable ์ƒํƒœ๋กœ ๋„˜์–ด๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.

์Šค๋ ˆ๋“œ์˜ ์ƒํƒœ ๋„์‹

4-2. Runnable ์ƒํƒœ

Running ์ƒํƒœ์˜ ๋ฐ”๋กœ ์ง์ „ ์ƒํƒœ์ด๊ณ , ์‹คํ–‰์„ ์œ„ํ•œ ๋ชจ๋“  ์ค€๋น„๊ฐ€ ๋๋‚ฌ์œผ๋ฉฐ CPU ์ž์›๋งŒ ์–ป์œผ๋ฉด ๋ฐ”๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

4-3. Running ์ƒํƒœ

์Šค๋ ˆ๋“œ์— ์ •์˜๋œ run() ๋ฉ”์†Œ๋“œ๊ฐ€ ์‹ค์ œ๋กœ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” ์ƒํƒœ์ด๋‹ค.

4-4. Not Running ์ƒํƒœ

Running ์ƒํƒœ์—์„œ CPU ์ž์›์„ ์žƒ์–ด ์‹คํ–‰์ด ์ค‘๋‹จ๋œ ์ƒํƒœ์ด๋‹ค. ์‹คํ–‰์„ ์ค‘๋‹จ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์€ ์Šค์Šค๋กœ Thread ํด๋ž˜์Šค์˜ sleep() ๋ฉ”์„œ๋“œ๋‚˜ Object ํด๋ž˜์Šค์˜ wait() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

4-5. Dead ์ƒํƒœ

์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋œ ์ƒํƒœ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์ข…๋ฃŒ๋œ ์Šค๋ ˆ๋“œ๊ฐ€ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋ ค๋ฉด ๋ฐ˜๋“œ์‹œ Startable ์ƒํƒœ๋ฅผ ๊ฑฐ์ณ์•ผ ํ•œ๋‹ค.

5. ์Šค๋ ˆ๋“œ์˜ ์ œ์–ด

์Šค๋ ˆ๋“œ์˜ ์ œ์–ด๋Š” ์Šค๋ ˆ๋“œ์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ์Šค๋ ˆ๋“œ๋ฅผ ์ œ์–ดํ•  ๋•Œ ์ฃผ์˜์ ์€ ๊ฐ€๊ธ‰์  ์Šค๋ ˆ๋“œ๋ฅผ ์ง์ ‘ ์ข…๋ฃŒ์‹œํ‚ค๋Š” ๊ฒƒ์„ ํ”ผํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

5-1. ์šฐ์„ ์ˆœ์œ„๋ฅผ ํ†ตํ•œ ์ œ์–ด

์ ˆ๋Œ€์ ์ธ ๋™์ž‘ ์ˆœ์„œ๋ฅผ ๋ณด์žฅํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์€ ์Šค๋ ˆ๋“œ๋Š” ๋‚ฎ์€ ์Šค๋ ˆ๋“œ์— ๋น„ํ•ด ์ƒ๋Œ€์ ์œผ๋กœ CPU ์ž์›์„ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ํ™•๋ฅ ์ด ๋†’์œผ๋ฏ€๋กœ ์šฐ์„ ์ˆœ์œ„๋ฅผ ํ†ตํ•ด ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Scratch {
    public static void main(String[] args) {

        Thread threadMIN = new Thread(new MyThread("MIN"));
        Thread threadNORM = new Thread(new MyThread("NORM"));
        Thread threadMAX = new Thread(new MyThread("MAX"));

        //์šฐ์„ ์ˆœ์œ„ ๋‚ฎ์Œ
        threadMIN.setPriority(Thread.MIN_PRIORITY);
        //์šฐ์„ ์ˆœ์œ„ ์ค‘๊ฐ„
        threadNORM.setPriority(Thread.NORM_PRIORITY);
        //์šฐ์„ ์ˆœ์œ„ ๋†’์Œ
        threadMAX.setPriority(Thread.MAX_PRIORITY);

        threadMIN.start();
        threadNORM.start();
        threadMAX.start();
    }
}

class MyThread implements Runnable {

    private String threadName;

    public MyThread(String threadName) {
        this.threadName = threadName;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
        }
        System.out.println("[" + threadName + "] END");
    }
}
๋ฐ˜๋“œ์‹œ ์œ„ ์ˆœ์„œ๋Œ€๋กœ ์ž‘๋™์„ ๋ณด์žฅํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค.

5-2. Thread ํด๋ž˜์Šค์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•œ ์ œ์–ด

Thread ํด๋ž˜์Šค์˜ yield(), join(), interrupt() , sleep() ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ์Šค๋ ˆ๋“œ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.

yield() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์•„์ฃผ ์งง์€ ์‹œ๊ฐ„๋™์•ˆ ์Šค๋ ˆ๋“œ๊ฐ€ Runnable ์ƒํƒœ๋กœ ๋“ค์–ด๊ฐ€์„œ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์— CPU๋ฅผ ์–‘๋ณดํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Scratch {

    public static void main(String[] args)  {

        Thread thread1 = new Thread(new MyThread(), "thd1");
        Thread thread2 = new Thread(new MyThread(), "thd2");

        thread1.start();
        thread2.start();
    }
}

class MyThread implements Runnable {

    @Override
    public void run() {

        String threadName = Thread.currentThread().getName();

        for (int i = 1; i <= 100; i++) {
            System.out.print("[" + threadName + "] ");
            if (threadName.equals("thd1")) Thread.yield();
        }
    }
}
๋น„๊ต์ (?) ๊ท ๋“ฑํ•˜๊ฒŒ ๊ต์ฐจ๋˜๊ณ  ์žˆ๋‹ค.

join() ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒฝ์šฐ ํŠน์ • ์Šค๋ ˆ๋“œ๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ ์Šค๋ ˆ๋“œ๋ฅผ ๋๋‚ด์ง€ ์•Š๊ณ  ๋ฉˆ์ถ”๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค. join() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์—๋Š” InterruptedException ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Scratch {

    public static void main(String[] args) throws InterruptedException {

        Thread thread1 = new Thread(new MyThread(), "thd1");
        Thread thread2 = new Thread(new MyThread(), "thd2");

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        System.out.println("==== main end ====");
    }
}

class MyThread implements Runnable {

    @Override
    public void run() {
        String threadName = Thread.currentThread().getName();
        for (int i = 1; i <= 5; i++) {
            System.out.println("[" + threadName + "] ");
        }
    }
}
join() ๋ฉ”์„œ๋“œ์˜ ์‚ฌ์šฉ ๊ฒฐ๊ณผ

์ด๋ฒˆ์—๋Š” ํŠน์ • ์Šค๋ ˆ๋“œ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋Œ€๊ธฐ์ƒํƒœ์— ์žˆ๋Š” ์Šค๋ ˆ๋“œ๋ฅผ ๊นจ์šฐ๋Š”(Not Running โ†’ Running) interrupt() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์‚ดํŽด๋ณด์ž.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class Scratch {

    public static void main(String[] args) throws InterruptedException {

        MyThread thread1 = new MyThread("thread1");
        MyThread thread2 = new MyThread("thread2");
        MyThread thread3 = new MyThread("thread3");

        thread1.setNextThread(thread2);
        thread2.setNextThread(thread3);
        thread3.setNextThread(thread1);

        thread1.start();
        thread2.start();
        thread3.start();

        try {
            //InterruptedException ์„ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.
            thread1.interrupt();
            thread1.join();
            thread2.join();
            thread3.join();
        } catch (InterruptedException e) {
            System.out.println(e);
        }

        System.out.println("===== main end =====");
    }
}

class MyThread extends Thread {

    private Thread nextThread;

    public MyThread(String threadName) {
        super(threadName);
    }

    @Override
    public void run() {
        String threadName = Thread.currentThread().getName();
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000000);
            } catch(InterruptedException e) {
                System.out.print("[" + threadName + "] -> ");
                //๋‹ค์Œ ์Šค๋ ˆ๋“œ๋ฅผ ๊นจ์šด๋‹ค.
                if(nextThread.isAlive()) nextThread.interrupt();
            }
        }
    }

    public void setNextThread(Thread nextThread) {
        this.nextThread = nextThread;
    }
}

์œ„์˜ ์ฝ”๋“œ๋Š” sleep ์ƒํƒœ์— ์žˆ๋Š” ์Šค๋ ˆ๋“œ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ interrupt ํ•˜๋ฉด์„œ ์Šค๋ ˆ๋“œ์˜ ํ๋ฆ„์„ ์ œ์–ดํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ธ์œ„์ ์œผ๋กœ ์Šค๋ ˆ๋“œ ์‹คํ–‰ ์ˆœ์„œ๋ฅผ ์ œ์–ดํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

6. ์Šค๋ ˆ๋“œ ๋™๊ธฐํ™”

ํ•˜๋‚˜์˜ ์ž์›์„ ๊ณต์œ ํ•˜๋Š” ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ ๊ฐ„์— ๋™๊ธฐํ™”๋ฅผ ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ฐ„์„ญ ํ˜„์ƒ์ด ๋ฐœ์ƒํ•œ๋‹ค. ๊ฐ„์„ญ ํ˜„์ƒ์ด๋ž€ ๊ณต์œ  ์ž์›์˜ ์ผ๊ด€์„ฑ์ด ๊นจ์ง€๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

๊ฐ„๋‹จํ•œ ์˜ˆ๋กœ ๊ณต์œ  ์ž์›์˜ ์ผ๊ด€์„ฑ์ด ๊นจ์ง€๋Š” ์ƒํ™ฉ์„ ์‚ดํŽด๋ณด์ž.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class Counter {
    
    private int c = 0;

    public void increment() {
        System.out.println("[" + Thread.currentThread().getName() + "] " + (++c));
    }
    public int getValue() {
        return c;
    }
}

class CounterRunner implements Runnable {

    private final Counter c;

    public CounterRunner(Counter c) {
        this.c = c;
    }

    public void run() {
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(500);
                c.increment();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

public class Scratch {
    public static void main(String[] args) throws InterruptedException {

        Counter c = new Counter();
        Thread threadA = new Thread(new CounterRunner(c), "A");
        Thread threadB = new Thread(new CounterRunner(c), "B");

        threadA.start();
        threadB.start();

        threadA.join();
        threadB.join();

        System.out.println("c = " + c.getValue());
    }
}

์Šค๋ ˆ๋“œ ๋‘๊ฐœ๊ฐ€ ํ•˜๋‚˜์˜ ๊ณต์œ  ์ž์›(Counter ๊ฐ์ฒด)์— ์ ‘๊ทผํ•ด ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์กฐ์ž‘ํ•˜๊ณ  ์žˆ๋‹ค. ์ •์ƒ์ ์œผ๋กœ ๊ธฐ๋Œ€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์€ ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ๊ฐ ๋‹ค์„ฏ ๋ฒˆ์”ฉ ๊ฐ์ฒด์˜ ๊ฐ’์„ ์ฆ๊ฐ€์‹œ์ผฐ์œผ๋ฏ€๋กœ 10์ด์ง€๋งŒ ์‹ค์ œ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ž.

์ž˜๋ชป๋œ ๊ฒฐ๊ณผ 1
์ž˜๋ชป๋œ ๊ฒฐ๊ณผ 2

๊ฒฐ๊ณผ๋Š” ๋งค๋ฒˆ ๋‹ค๋ฅด์ง€๋งŒ(์ •์ƒ์ ์ธ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ฌ๋•Œ๋„ ์žˆ๋‹ค), ์˜ฌ๋ฐ”๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์žฅํ•˜์ง€ ๋ชปํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋ณ‘๋ ฌ ์Šค๋ ˆ๋“œ๊ฐ„์˜ ๊ฐ„์„ญ ํ˜„์ƒ์œผ๋กœ ์ธํ•ด ์ผ๊ด€์„ฑ์„ ํ•ด์น˜๋Š” ๋ฌธ์ œ๋ฅผ ๋™์‹œ์„ฑ ์ด์Šˆ(Concurrency Issue)๋ผ๊ณ  ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฌํ•œ ๋™์‹œ์„ฑ ์ด์Šˆ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด synchronized ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

synchronized ํ‚ค์›Œ๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฒ”์œ„์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ
  • ์ •์  ๋ฉ”์„œ๋“œ
  • ์ฝ”๋“œ ๋ธ”๋ก

JAVA๋Š” ๋™๊ธฐํ™”๋ฅผ ์œ„ํ•ด ๋ชจ๋‹ˆํ„ฐ๋ผ๋Š” ๋™๊ธฐํ™” ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค. ๋ชจ๋‹ˆํ„ฐ ๊ธฐ๋ฒ•์€ ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด synchronized๋กœ ์„ ์–ธ๋œ ์˜์—ญ ๋‚ด์—๋Š” ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ์ง„์ž…ํ•˜๋„๋ก ํ—ˆ์šฉํ•˜๋Š” ๊ธฐ๋ฒ•์ด๋‹ค. ๋ชจ๋‹ˆํ„ฐ์— ํŠน์ • ์Šค๋ ˆ๋“œ๊ฐ€ ์ง„์ž…ํ•˜๋ฉด ๋ชจ๋‹ˆํ„ฐ ๋ฝ์„ ํš๋“ํ•˜๊ณ  ๊ทธ ์™ธ์˜ ์Šค๋ ˆ๋“œ๋Š” ํ์—์„œ ๋Œ€๊ธฐํ•œ๋‹ค.

์œ„์˜ ์ฝ”๋“œ์— synchronized ํ‚ค์›Œ๋“œ๋ฅผ ์ ์šฉํ•ด๋ณด์ž.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ...
// Counter.class
public synchronized void increment() {
    System.out.println("[" + Thread.currentThread().getName() + "] " + (++c));
}
// ...

// ...
// Counter.class
public void increment() {
    synchronized (this) {
        System.out.println("[" + Thread.currentThread().getName() + "] " + (++c));
    }
}
// ...

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ ์ „์ฒด๋ฅผ ๋™๊ธฐํ™” ์˜์—ญ์œผ๋กœ ๋งŒ๋“ค๊ฑฐ๋‚˜, ํŠน์ • ์ฝ”๋“œ๋งŒ ๋™๊ธฐํ™” ์ž‘์—…์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๋™๊ธฐํ™” ๋ธ”๋Ÿญ์„ ๋งŒ๋“ค์–ด ์ค„ ์ˆ˜ ์žˆ๋‹ค. ๋™๊ธฐํ™” ์˜์—ญ์„ ์ง€์ •ํ•œ ํ›„ ์•ž์„  ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ํ•œ๋ฒˆ ์‹คํ–‰ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

Refferences

  1. ๐Ÿ”—Guide to the Synchronized Keyword in Java - Baeldung
  2. ๐Ÿ”—What is a Monitor in Computer Science? - Baeldung
  3. ๐Ÿ”—Guide to the Synchronized Keyword in Java - Baeldung
  4. ๐Ÿ”—๋ชจ๋‹ˆํ„ฐ(๋™๊ธฐํ™”) - ์œ„ํ‚ค๋ฐฑ๊ณผ
  5. KNOU - JAVA ํ”„๋กœ๊ทธ๋ž˜๋ฐ 11๊ฐ• ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

ํƒœ๊ทธ: ,

์นดํ…Œ๊ณ ๋ฆฌ:

์—…๋ฐ์ดํŠธ: