[Spring] ์Šค๋ ˆ๋“œ ๋กœ์ปฌ, ThreadLocal

2022. 5. 31. 00:41ใ†Backend/๐ŸŒฟ Spring

์Šค๋ ˆ๋“œ ๋กœ์ปฌ

์—ฌ๋Ÿฌ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ์กด์žฌํ•  ๋•Œ, ํ•ด๋‹น ์Šค๋ ˆ๋“œ๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ํŠน๋ณ„ํ•œ ์ €์žฅ์†Œ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ๋” ํ’€์–ด์„œ ์ด์•ผ๊ธฐ ํ•ด๋ณด์ž. ๋งŒ์•ฝ ์„œ๋กœ ๋‹ค๋ฅธ ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ํ•˜๋‚˜์˜ ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•œ๋‹ค๊ณ  ํ•  ๋•Œ, ์ด ๋ณ€์ˆ˜๋Š” ๊ณต์œ  ์ž์›์œผ๋กœ ๋™์‹œ์„ฑ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋‹ค๋ถ„ํ•˜๋‹ค. ThreadLocal ํด๋ž˜์Šค๋Š” ์˜ค์ง ํ•œ ์Šค๋ ˆ๋“œ์— ์˜ํ•ด ์ฝ๊ณ /์“ฐ์—ฌ์งˆ ์ˆ˜ ์žˆ๋Š” ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

 

๊ฐ€๋ น Thread A ๊ฐ€ ThreadLocal ๋ณ€์ˆ˜( tLocal ) ์— ์ ‘๊ทผํ•˜์—ฌ a ๋ผ๋Š” ๋ฌธ์ž๋ฅผ ์ €์žฅํ•œ๋‹ค๊ณ  ํ•˜์ž. ๋™์‹œ์— Thread  B ์—์„œ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ tLocal ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•˜์—ฌ, b ๋ผ๋Š” ๋ฌธ์ž๊ฐ’์„ ์ €์žฅํ•œ๋‹ค๊ณ  ํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? a ๋ผ๋Š” ๋ฌธ์ž๋ฅผ b ๊ฐ€ ๋ฎ์–ด ๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์•„๋ž˜ ์ฒ˜๋Ÿผ ๊ฐ ์Šค๋ ˆ๋“œ๋ณ„ ์ „์šฉ ์ €์žฅ์†Œ์— ๊ฐ๊ฐ์˜ ๊ฐ’์ด ์ €์žฅ๋œ๋‹ค. ์ฆ‰ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ๊ณต์œ  ์ž์›์˜ ๋™์‹œ์„ฑ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

 

 

์Šค๋ ˆ๋“œ ๋กœ์ปฌ ๋ผ์ดํ”„ ์‚ฌ์ดํด

์Šค๋ ˆ๋“œ ๋กœ์ปฌ ์ƒ์„ฑ

ThreadLocal<String> threadLocal = new ThreadLocal<>();

์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•˜์—ฌ ํƒ€์ž… ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์šฐ์„  String ์œผ๋กœ ์ง€์ •ํ•ด๋ณด์ž.

 

 

์Šค๋ ˆ๋“œ ๋กœ์ปฌ ์“ฐ๊ธฐ/์ฝ๊ธฐ

threadLocal.set("a") // thread local ๊ฐ’ ์ €์žฅ
threadLocal.get() // ์ €์žฅ๋œ ๊ฐ’ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

์„ ์–ธ๋œ threadLocal ๋ณ€์ˆ˜์˜ set(), get() ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด ์Šค๋ ˆ๋“œ๋กœ์ปฌ ๊ฐ’์„ ์“ฐ๊ณ  ์ฝ์„ ์ˆ˜ ์žˆ๋‹ค.

์•„๋ฌด ๊ฐ’๋„ ์ €์žฅ๋˜์ง€ ์•Š์€ ์Šค๋ ˆ๋“œ๋กœ์ปฌ์˜ ๊ฐ’์„ ์ฝ์œผ๋ฉด(get()) null ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

@Slf4j
public class ThreadLocalServiceTest {

    private ThreadLocal<String> threadLocal = new ThreadLocal<>();
    
    @Test
    void field() {

        Runnable userC = () -> {
            log.info("start");

            String value = threadLocal.get();
            log.info("value : {}", value);

            log.info("set threadLocal value : A");
            threadLocal.set("A");

            value = threadLocal.get();
            log.info("threadLocal : {}", value);
        };

        Thread threadC = new Thread(userC);
        threadC.setName("thread-C");
        threadC.start();

    }
}

 

์Šค๋ ˆ๋“œ ๋กœ์ปฌ ๊ฐ’ ์ œ๊ฑฐ

์Šค๋ ˆ๋“œ๋กœ์ปฌ์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•˜๊ณ  ๋‚˜๋ฉด ๋ฐ˜๋“œ์‹œ ThreadLocal.remove() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ, ์Šค๋ ˆ๋“œ ๋กœ์ปฌ์— ์ €์žฅ๋œ ๊ฐ’์„ ์ œ๊ฑฐํ•ด์•ผ ํ•œ๋‹ค.

์Šค๋ ˆ๋“œ ๋กœ์ปฌ์˜ ๊ฐ’์„ ์ œ๊ฑฐํ•˜์ง€ ์•Š์œผ๋ฉด ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”์ง€ ๋‹ค์Œ ์ผ€์ด์Šค๋ฅผ ํ™•์ธํ•ด๋ณด์ž.

1. ์‚ฌ์šฉ์ž A ๊ฐ€ ์ €์žฅ HTTP ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.

2. WAS ๋Š” ์Šค๋ ˆ๋“œํ’€์—์„œ ์Šค๋ ˆ๋“œ๋ฅผ ํ•˜๋‚˜ ์กฐํšŒํ•œ๋‹ค.

3. ํ•ด๋‹น ์Šค๋ ˆ๋“œ๋Š” thread-A ๊ฐ€ ํ• ๋‹น ๋˜์—ˆ๊ณ , ์‚ฌ์šฉ์ž A ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์Šค๋ ˆ๋“œ ๋กœ์ปฌ์— ์ €์žฅํ•œ๋‹ค.

4. ์Šค๋ ˆ๋“œ ๋กœ์ปฌ thread-A ์ „์šฉ ๋ณด๊ด€์†Œ์— ์‚ฌ์šฉ์žA ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๊ด€ํ•œ๋‹ค.

5. ์‚ฌ์šฉ์ž A ์˜ HTTP ์š”์ฒญ์ด ์ข…๋ฃŒ๋˜๋ฉด, thread-A ๋Š” ๋‹ค์‹œ ์Šค๋ ˆ๋“œ ํ’€์— ๋ฐ˜ํ™˜๋œ๋‹ค.

6. thread-A ๋Š” ์Šค๋ ˆ๋“œ ํ’€์„ ํ†ตํ•ด์„œ ์žฌ์‚ฌ์šฉ ๋  ์ˆ˜ ์žˆ๋‹ค.

 

1. ์‚ฌ์šฉ์ž B ์—์„œ HTTP ์กฐํšŒ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.

2. ์Šค๋ ˆ๋“œ ํ’€์—์„œ ํ•˜ํ•„ thread-A ๊ฐ€ ํ• ๋‹น๋˜์—ˆ๋‹ค.

3. ์กฐํšŒ ์š”์ฒญ์ด๊ธฐ ๋•Œ๋ฌธ์— ์Šค๋ ˆ๋“œ ํ’€์˜ thread-A  ์ „์šฉ ๊ณต๊ฐ„์—์„œ, ์ด์ „์— ์ €์žฅํ•ด๋‘” ๊ฐ’์ด ์กฐํšŒ๋œ๋‹ค.

4. ์ฆ‰ ์‚ฌ์šฉ์ž B ๊ฐ€ ์˜ˆ์ƒํ•œ ์กฐํšŒ ๊ฒฐ๊ณผ๊ฐ€ ์•„๋‹Œ, ์‚ฌ์šฉ์ž A ๊ฐ€ ์ €์žฅํ•ด๋‘” ๊ฐ’์ด ์กฐํšŒ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

 

๊ฒฐ๊ณผ์ ์œผ๋กœ, ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ์‚ฌ์šฉ์ž A ์˜ ์š”์ฒญ์ด ๋๋‚  ๋•Œ ์“ฐ๋ ˆ๋“œ ๋กœ์ปฌ์˜ ๊ฐ’์„ ThreadLocal.remove() ๋ฅผ ํ†ตํ•ด์„œ ๊ผญ ์ œ๊ฑฐํ•ด์•ผ ํ•œ๋‹ค.

 

 

 

์ž๋ฃŒ ์ถœ์ฒ˜ : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B3%A0%EA%B8%89%ED%8E%B8