Skip to content

Latest commit

ย 

History

History
113 lines (89 loc) ยท 4.95 KB

thread_local.md

File metadata and controls

113 lines (89 loc) ยท 4.95 KB

ThreadLocal

image

์ž๋ฐ”์—์„œ ์Šค๋ ˆ๋“œ๋Š” ์˜ค์ง ์ž์‹ ๋งŒ์ด ์ ‘๊ทผํ•ด์„œ ์ฝ๊ณ  ์“ธ ์ˆ˜ ์žˆ๋Š” ๋กœ์ปฌ ๋ณ€์ˆ˜ ์ €์žฅ์†Œ ThreadLocal์„ ์ œ๊ณตํ•œ๋‹ค.
๊ฐ ์Šค๋ ˆ๋“œ๋Š” ๊ณ ์œ ํ•œ ThreadLocal ๊ฐ์ฒด๋ฅผ ์†์„ฑ์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ ThreadLocal์€ ์Šค๋ ˆ๋“œ ๊ฐ„ ๊ฒฉ๋ฆฌ๋˜์–ด ์žˆ๋‹ค.

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

public class Thread implements Runnable {

    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
}

์Šค๋ ˆ๋“œ๋Š” ThreadLocal์— ์žˆ๋Š” ThreadLocalMap ๊ฐ์ฒด๋ฅผ ์ž์‹ ์˜ threadLocals ์†์„ฑ์— ์ €์žฅํ•œ๋‹ค.
์Šค๋ ˆ๋“œ ์ƒ์„ฑ ์‹œ threadLocals ๊ธฐ๋ณธ ๊ฐ’์€ null์ด๋ฉฐ ThreadLocal์— ๊ฐ’์„ ์ €์žฅํ•  ๋–„ ThreadLocalMap์ด ์ƒ์„ฑ๋˜๊ณ  threadLocals์™€ ์—ฐ๊ฒฐ๋œ๋‹ค.

ThreadLocalMap์€ ์Šค๋ ˆ๋“œ๋งˆ๋‹ค ํ•ญ์ƒ ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑ๋˜์–ด ์Šค๋ ˆ๋“œ ์Šคํƒ์— ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทผ๋ณธ์ ์œผ๋กœ ์Šค๋ ˆ๋“œ๊ฐ„ ๋ฐ์ดํ„ฐ ๊ณต์œ ๊ฐ€ ๋  ์ˆ˜ ์—†๊ณ  ๋™์‹œ์„ฑ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์Šค๋ ˆ๋“œ ํ’€์„ ์‚ฌ์šฉํ•ด์„œ ์Šค๋ ˆ๋“œ๋ฅผ ์šด์šฉํ•œ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ThreadLocal์— ์ €์žฅ๋œ ๊ฐ’์„ ์‚ญ์ œํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค.
์Šค๋ ˆ๋“œ ํ’€์€ ์Šค๋ ˆ๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด์ „ ์Šค๋ ˆ๋“œ์—์„œ ThreadLocal์— ์ €์žฅ๋œ ๊ฐ’์„ ์‚ญ์ œํ•˜์ง€ ์•Š๊ณ  ์žฌ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

public class ThreadLocal<T> {

    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

    private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            map.set(this, value);
        } else {
            createMap(t, value);
        }
        if (this instanceof TerminatingThreadLocal) {
            TerminatingThreadLocal.register((TerminatingThreadLocal<?>) this);
        }
        return value;
    }
}

ThreadLocal์€ Thread์™€ ThreadLocalMap์„ ์—ฐ๊ฒฐํ•˜์—ฌ ์Šค๋ ˆ๋“œ ์ „์šฉ ์ €์žฅ์†Œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋Š”๋ฐ ์ด๊ฒƒ์ด ๊ฐ€๋Šฅํ•œ ์ด์œ ๋Š” ๋ฐ”๋กœ Thread.currentThread๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Thread.currentThread()๋Š” ํ˜„์žฌ ์‹คํ–‰์ค‘์˜ ์Šค๋ ˆ๋“œ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์œผ๋กœ์„œ CPU๋Š” ์˜ค์ง ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ํ• ๋‹น๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ์Šค๋ ˆ๋“œ์˜ ๋กœ์ปฌ ๋ณ€์ˆ˜๋ฅผ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. ThreadLocal์—์„œ ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†๋‹ค๋ฉด ์Šค๋ ˆ๋“œ๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์—†์„ ๊ฒƒ์ด๋‹ค. ๋•Œ๋ฌธ์— Thread.currentThread()๋Š” ThreadLocal์˜ ์ค‘์š”ํ•œ ์‹๋ณ„ ๊ธฐ์ค€์ด ๋œ๋‹ค.

InheritableThreadLocal

InheritableThreadLocal์€ ThreadLocal์˜ ํ™•์žฅ ๋ฒ„์ „์œผ๋กœ์„œ ๋ถ€๋ชจ ์Šค๋ ˆ๋“œ๋กœ๋ถ€ํ„ฐ ์ž์‹์Šค๋ ˆ๋“œ๋กœ ๊ฐ’์„ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๋ถ€๋ชจ ์Šค๋ ˆ๋“œ๊ฐ€ InheritableThreadLocal ๋ณ€์ˆ˜์— ๊ฐ’์„ ์„ค์ •ํ•˜๋ฉด, ํ•ด๋‹น ๋ถ€๋ชจ ์Šค๋ ˆ๋“œ๋กœ๋ถ€ํ„ฐ ์ƒ์„ฑ๋œ ์ž์‹ ์Šค๋ ˆ๋“œ๋“ค์€ ๋ถ€๋ชจ์˜ ๊ฐ’์„ ์ƒ์†๋ฐ›๊ฒŒ ๋œ๋‹ค. ์ž์‹ ์Šค๋ ˆ๋“œ๊ฐ€ ์ƒ์†๋ฐ›์€ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋”๋ผ๋„ ๋ถ€๋ชจ ์Šค๋ ˆ๋“œ์˜ ๊ฐ’์—๋Š” ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค.

class Thread implements Runnable {
    private Thread(ThreadGroup g, Runnable target, String name,
                   long stackSize, AccessControlContext acc,
                   boolean inheritThreadLocals) {
        ...
        Thread parent = currentThread(); // main Thread
        ...
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); // main Thread์˜ ThreadLocalMap์„ ๋ณต์‚ฌ
        ...
    }
}

class ThreadLocal<T> {
    static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
        return new ThreadLocalMap(parentMap);
    }
}

Reference