volatile

image
  • ๊ธฐ๋ณธ์ ์ธ ๋ฉ€ํ‹ฐ ํ”„๋กœ์„ธ์Šค์˜ ๊ตฌ์กฐ.

  • Core(CPU) ๋ณ„๋กœ, ์บ์‹œ๋“ค์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , L3 ๋ฅผ ๊ฑฐ์ณ RAM์œผ๋กœ ๊ฐ€๋Š” ๊ตฌ์กฐ.

  • ๋งŒ์•ฝ์— L1 cache์—์„œ A ๋ฉ”๋ชจ๋ฆฌ์˜ ๊ฐ’์— ์—…๋ฐ์ดํŠธ๊ฐ€ ์ผ์–ด๋‚˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

    • ๊ทธ ์—…๋ฐ์ดํŠธ๊ฐ€ RAM์— ์ „ํŒŒ๋ ๋•Œ ๊นŒ์ง€๋Š” ๋‹ค๋ฅธ ์ฝ”์–ด์—์„œ๋Š” ์•Œ ์ˆ˜ ์—†์Œ. (์—…๋ฐ์ดํŠธ๊ฐ€ ์•ˆ๋˜์—ˆ์œผ๋‹ˆ)

    • data inconsistency

  • ์ด ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ํ•ด๋‹น ๋ณ€์ˆ˜์˜ ๋ณ€ํ™”๊ฐ€ main memory๊นŒ์ง€ ๋ฐ”๋กœ ์ „ํŒŒ๋จ์„ ์˜๋ฏธ. ([[compare-and-swap]] ๋ผ๋Š” ๋ฐฉ๋ฒ•์„ ์ด์šฉํ•ด์„œ)

Memory Visibility

public class TaskRunner {

    private static int number;
    private static boolean ready;

    private static class Reader extends Thread {

        @Override
        public void run() {
            while (!ready) {
                Thread.yield();
            }

            System.out.println(number);
        }
    }

    public static void main(String[] args) {
        new Reader().start();
        number = 42;
        ready = true;
    }
}
  • ์Šค๋ ˆ๋“œ๋Š” 2๊ฐœ main, runner thread

  • main thread์—์„œ ์—…๋ฐ์ดํŠธ ํ•œ ๋ณ€์ˆ˜ (number, ready) ๊ฐ€ runner thread ์—๊ฒŒ๋„ ๋ฐ”๋กœ ์ฝ์„ ์ˆ˜ ์žˆ์„๊นŒ?

    • ๊ทธ๋Ÿด ์ˆ˜๋„, ์‹œ๊ฐ„์ด ๊ฑธ๋ฆด ์ˆ˜๋„, ํ˜น์€ ์—…๋ฐ์ดํŠธ๊ฐ€ ์•ˆ๋  ์ˆ˜๋„ ์žˆ์Œ.

    • ์™œ?

    • processors tend to queue those writes in a special write buffer

    • ๋ฐ”๋กœ ์ ์šฉ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ, write buffer์— queue ๋ฅผ ๋˜์ ธ์„œ, ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚œ ํ›„์— main memory์— ๋ฐ˜์˜๋˜๊ธฐ ๋•Œ๋ฌธ

  • ์ฆ‰ ์ •๋ฆฌํ•˜์ž๋ฉด,

    • main thread๊ฐ€ number, ready ๋ณ€์ˆ˜๋ฅผ ์—…๋ฐ์ดํŠธ ํ–ˆ์„ ๋•Œ, reader thread๊ฐ€ ์—…๋ฐ์ดํŠธ ๋œ ๋ณ€์ˆ˜๋ฅผ ์ฝ๋Š” ๋‹ค๋Š” ๋ณด์žฅ์ด ์—†์Œ.

    • ์‹ฌ์ง€์–ด programe order (number -> ready) ์ˆœ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•ด์„œ ๋ณด๊ธฐ ๋ณด๋‹ค๋Š” ์•„์˜ˆ ๋‹ค๋ฅธ ์ˆœ์„œ (ready -> number) ์ˆœ์œผ๋กœ๋„ ๋ณผ ์ˆ˜ ์žˆ์Œ. (๊ฐœ๋ฐœ์ž์˜ ์˜๋„์™€๋Š” ์•„์˜ˆ ๋‹ค๋ฅด๊ฒŒ..)

    • ready = true๋กœ ๋ฐ”๋€Œ์—ˆ์ง€๋งŒ number๋Š” ์—…๋ฐ์ดํŠธ ๋˜์ง€ ์•Š์€ ์ฑ„ 0์„ ํ”„๋ฆฐํŠธ ํ•˜๊ณ  ์ข…๋ฃŒ๋  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๋œป์ธ๋“ฏ.

To ensure programm order

  • To ensure that updates to variables propagate predictably to other thread

  • ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•œ ์ˆœ์„œ๋Œ€๋กœ ๋ณ€์ˆ˜๋“ค์ด ์—…๋ฐ์ดํŠธ ๋˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด์„ ?

  • volatile ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉ.

public class TaskRunner {

    private volatile static int number;
    private volatile static boolean ready;

    // same as before
}
  • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด.. number ์—…๋ฐ์ดํŠธ ํ›„์— ready๊ฐ€ ์—…๋ฐ์ดํŠธ ๋œ๋‹ค.

  • 42 print ํ›„ ์ข…๋ฃŒ๋ฅผ ์˜ˆ์ธกํ•  ์ˆ˜ ์žˆ์„๋“ฏ.

For multithreaded applications

  • ์ผ๊ด€์ ์ธ ํ–‰๋™์„ ์œ„ํ•ด์„  2๊ฐ€์ง€ ๋ฃฐ์„ ์ง€์ผœ์•ผํ•จ.

    1. Mutual Exclusion : ์น˜๋ช…์ ์ธ ๋ถ€๋ถ„์—๋Š” ํ•œ๋ฒˆ์— ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ์‹คํ–‰ํ•˜๋„๋ก.

    2. Visibility : ๊ณต์œ ๋œ ์ž์›์— ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋กœ ๋ถ€ํ„ฐ ๋งŒ๋“ค์–ด์ง„ ๋ณ€ํ™”๋“ค์€, ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋“ค์ด ๋ณผ ์ˆ˜ ์žˆ์–ด์•ผํ•จ. ์™œ? data consistency ๋ฅผ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด

  • [[sy]] ๋ฉ”์„œ๋“œ๋Š” 1,2 ๋ฒˆ์˜ ๋ฃฐ์„ ๋ชจ๋‘ ๋งŒ์กฑ ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Œ.

    • ๋‹ค๋งŒ ์ƒ๋‹นํ•œ ์ž์›์„ ์†Œ๋ชจ.

  • ๊ทธ๋ ‡์ง€๋งŒ [[volatile]] ๋Š” mutual exclusion ์—†์ด 2๋ฒˆ visibility ์ธก๋ฉด์„ ๋งŒ์กฑ์‹œํ‚ด.

์ฐธ๊ณ 

Last updated

Was this helpful?