ํ๋ฐ์ฑ ๋ณ์ ์ฌ์ฉ ์ง์นจ
๋ธ๋ผ์ด์ธ ๊ฒ์ธ (Brian Goetz) 2007๋
6์ 19์ผ ์๋ณธ: ๋ณ๋์ฑ ๊ด๋ฆฌ Java์ ํ๋ฐ์ฑ ๋ณ์๋ "๋๊ธฐํ-๋ผ์ดํธ"๋ผ๊ณ ๋ถ๋ฆด ์ ์์ต๋๋ค. ๋๊ธฐํ๋ ๋ธ๋ก๋ณด๋ค ์ฌ์ฉํ๋ ๋ฐ ๋ ์ ์ ์ฝ๋๊ฐ ํ์ํ๊ณ ์ข
์ข
๋ ๋น ๋ฅด๊ฒ ์คํ๋์ง๋ง ๋๊ธฐํ๋ ๋ธ๋ก์ด ์ํํ๋ ์์
์ ์ผ๋ถ๋ง ์ํํ ์ ์์ต๋๋ค. ์ด ๊ธฐ์ฌ์์๋ ํ๋ฐ์ฑ์ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํ ๋ช ๊ฐ์ง ํจํด๊ณผ ์ด๋ฅผ ์ฌ์ฉํ์ง ๋ง์์ผ ํ ๊ณณ์ ๋ํ ๋ช ๊ฐ์ง ๊ฒฝ๊ณ ๋ฅผ ์ ์ํฉ๋๋ค. ์ ๊ธ์๋ ์ํธ ๋ฐฐ์ (๋ฎคํ
์ค)์ ๊ฐ์์ฑ์ ๋ ๊ฐ์ง ์ฃผ์ ๊ธฐ๋ฅ์ด ์์ต๋๋ค. ์ํธ ๋ฐฐ์ ๋ ์ ๊ธ์ด ํ ๋ฒ์ ํ๋์ ์ค๋ ๋์ ์ํด์๋ง ์ ์ง๋ ์ ์์์ ์๋ฏธํ๋ฉฐ, ์ด ์์ฑ์ ํ ๋ฒ์ ํ๋์ ์ค๋ ๋๋ง ์ฌ์ฉํ๋๋ก ๊ณต์ ๋ฆฌ์์ค์ ๋ํ ์ก์ธ์ค ์ ์ด ํ๋กํ ์ฝ์ ๊ตฌํํ๋ ๋ฐ ์ฌ์ฉ๋ ์ ์์ต๋๋ค. ๊ฐ์์ฑ์ ๋ณด๋ค ๋ฏธ๋ฌํ ๋ฌธ์ ์ด๋ฉฐ, ๊ทธ ๋ชฉ์ ์ ์ ๊ธ์ด ํด์ ๋๊ธฐ ์ ์ ๊ณต์ฉ ๋ฆฌ์์ค์ ๋ํ ๋ณ๊ฒฝ ์ฌํญ์ด ํด๋น ์ ๊ธ์ ์ธ๊ณ๋ฐ๋ ๋ค์ ์ค๋ ๋์ ํ์๋๋๋ก ํ๋ ๊ฒ์
๋๋ค. ๋๊ธฐํ๊ฐ ๊ฐ์์ฑ์ ๋ณด์ฅํ์ง ์์ผ๋ฉด ์ค๋ ๋๊ฐ ๊ณต์ฉ ๋ณ์์ ๋ํด ์ค๋๋๊ฑฐ๋ ์๋ชป๋ ๊ฐ์ ์์ ํ ์ ์์ผ๋ฉฐ ์ด๋ก ์ธํด ์ฌ๋ฌ ๊ฐ์ง ์ฌ๊ฐํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
ํ๋ฐ์ฑ ๋ณ์
ํ๋ฐ์ฑ ๋ณ์๋ ๋๊ธฐํ๋ ๋ณ์์ ๊ฐ์์ฑ ์์ฑ์ ๊ฐ์ง์ง๋ง ์์์ฑ์ ๋ถ์กฑํฉ๋๋ค. ์ด๋ ์ค๋ ๋๊ฐ ์๋์ผ๋ก ํ๋ฐ์ฑ ๋ณ์์ ์ต์ ๊ฐ์ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์ค๋ ๋ ์์ ์ฑ์ ์ํด ์ฌ์ฉ๋ ์ ์์ง๋ง ๋งค์ฐ ์ ํ๋ ๊ฒฝ์ฐ, ์ฆ ์ฌ๋ฌ ๋ณ์ ์ฌ์ด ๋๋ ๋ณ์์ ํ์ฌ ๊ฐ๊ณผ ๋ฏธ๋ ๊ฐ ์ฌ์ด์ ๊ด๊ณ๋ฅผ ๋์
ํ์ง ์๋ ๊ฒฝ์ฐ์
๋๋ค
. ๋ฐ๋ผ์ ํ๋ฐ์ฑ๋ง์ผ๋ก๋ ์นด์ดํฐ, ๋ฎคํ
์ค ๋๋ ๋ถ๋ณ ๋ถ๋ถ์ด ์ฌ๋ฌ ๋ณ์์ ์ฐ๊ฒฐ๋ ํด๋์ค(์: "start <=end")๋ฅผ ๊ตฌํํ๋ ๋ฐ ์ถฉ๋ถํ์ง ์์ต๋๋ค. ๋จ์์ฑ ๋๋ ํ์ฅ์ฑ์ด๋ผ๋ ๋ ๊ฐ์ง ์ฃผ์ ์ด์ ์ค ํ๋๋ก ํ๋ฐ์ฑ ์ ๊ธ์ ์ ํํ ์ ์์ต๋๋ค. ์ผ๋ถ ์ธ์ด ๊ตฌ์ฑ์ ์ ๊ธ ๋์ ํ๋ฐ์ฑ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ฉด ํ๋ก๊ทธ๋จ ์ฝ๋๋ก ์์ฑํ๊ธฐ๊ฐ ๋ ์ฝ๊ณ ๋์ค์ ์ฝ๊ณ ์ดํดํ๊ธฐ๊ฐ ๋ ์ฝ์ต๋๋ค. ๋ํ ์ ๊ธ๊ณผ ๋ฌ๋ฆฌ ์ค๋ ๋๋ฅผ ์ฐจ๋จํ ์ ์์ผ๋ฏ๋ก ํ์ฅ์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ์ ์ต๋๋ค. ์ฐ๊ธฐ๋ณด๋ค ์ฝ๊ธฐ๊ฐ ๋ ๋ง์ ์ํฉ์์๋ ํ๋ฐ์ฑ ๋ณ์๊ฐ ์ ๊ธ์ ๋นํด ์ฑ๋ฅ์์ ์ด์ ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
ํ๋ฐ์ฑ ๋ฌผ์ง์ ์ฌ๋ฐ๋ฅธ ์ฌ์ฉ์ ์ํ ์กฐ๊ฑด
์ ํ๋ ์ํฉ์์๋ ์ ๊ธ์ ํ๋ฐ์ฑ ์ ๊ธ์ผ๋ก ๊ต์ฒดํ ์ ์์ต๋๋ค. ์ค๋ ๋๋ก๋ถํฐ ์์ ํ๋ ค๋ฉด ๋ ๊ฐ์ง ๊ธฐ์ค์ ๋ชจ๋ ์ถฉ์กฑํด์ผ ํฉ๋๋ค.
- ๋ณ์์ ๊ธฐ๋ก๋๋ ๋ด์ฉ์ ํ์ฌ ๊ฐ๊ณผ ๋ฌด๊ดํฉ๋๋ค.
- ๋ณ์๋ ๋ค๋ฅธ ๋ณ์์์ ๋ถ๋ณ์ฑ์ ์ฐธ์ฌํ์ง ์์ต๋๋ค.
๊ฐ๋จํ ๋งํด์, ์ด๋ฌํ ์กฐ๊ฑด์ ํ๋ฐ์ฑ ๋ณ์์ ์ธ ์ ์๋ ์ ํจํ ๊ฐ์ด ๋ณ์์ ํ์ฌ ์ํ๋ฅผ ํฌํจํ์ฌ ํ๋ก๊ทธ๋จ์ ๋ค๋ฅธ ๋ชจ๋ ์ํ์ ๋ฌด๊ดํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์ฒซ ๋ฒ์งธ ์กฐ๊ฑด์ ์ค๋ ๋๋ก๋ถํฐ ์์ ํ ์นด์ดํฐ๋ก ํ๋ฐ์ฑ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ ์ธํฉ๋๋ค. ์ฆ๋ถ(x++)์ ๋จ์ผ ์์
์ฒ๋ผ ๋ณด์ด์ง๋ง ์ค์ ๋ก๋ ํ๋ฐ์ฑ์ด ์ ๊ณตํ์ง ์๋ ์์์ ์ผ๋ก ์ํ๋์ด์ผ ํ๋ ์ฝ๊ธฐ-์์ -์ฐ๊ธฐ ์์
์ ์ ์ฒด ์ํ์ค์
๋๋ค. ์ ํจํ ์์
์ ์ํด์๋ x ๊ฐ์ด ์์
์ ๋ฐ์ ๊ฑธ์ณ ๋์ผํ๊ฒ ์ ์ง๋์ด์ผ ํ๋๋ฐ, ์ด๋ ํ๋ฐ์ฑ์ ์ฌ์ฉํ์ฌ ๋ฌ์ฑํ ์ ์์ต๋๋ค. (๋จ, ํ๋์ ์ค๋ ๋์์๋ง ๊ฐ์ ์ฐ๋ ๊ฒ์ด ๋ณด์ฅ๋๋ค๋ฉด ์ฒซ ๋ฒ์งธ ์กฐ๊ฑด์ ์๋ตํ ์ ์์ต๋๋ค.) ๋๋ถ๋ถ์ ์ํฉ์์ ์ฒซ ๋ฒ์งธ ๋๋ ๋ ๋ฒ์งธ ์กฐ๊ฑด์ด ์๋ฐ๋๋ฏ๋ก ํ๋ฐ์ฑ ๋ณ์๋ ๋๊ธฐํ๋ ๋ณ์๋ณด๋ค ์ค๋ ๋ ์์ ์ฑ์ ๋ฌ์ฑํ๊ธฐ ์ํด ๋ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ ์ ๊ทผ ๋ฐฉ์์ด ๋ฉ๋๋ค. ๋ชฉ๋ก 1์ ์ซ์ ๋ฒ์๊ฐ ํฌํจ๋ ์ค๋ ๋๋ก๋ถํฐ ์์ ํ์ง ์์ ํด๋์ค๋ฅผ ๋ณด์ฌ์ค๋๋ค. ์ฌ๊ธฐ์๋ ๋ถ๋ณ์ด ํฌํจ๋ฉ๋๋ค. ํํ์ ํญ์ ์ํ๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ต๋๋ค.
@NotThreadSafe public class NumberRange { private int lower, upper; public int getLower() { return lower; } public int getUpper() { return upper; } public void setLower(int value) { if (value > upper) throw new IllegalArgumentException(...); lower = value; } public void setUpper(int value) { if (value < lower) throw new IllegalArgumentException(...); upper = value; } }
๋ฒ์ ์ํ ๋ณ์๋ ์ด๋ฌํ ๋ฐฉ์์ผ๋ก ์ ํ๋๋ฏ๋ก ํด๋์ค๊ฐ ์ค๋ ๋๋ก๋ถํฐ ์์ ํ์ง ํ์ธํ๊ธฐ ์ํด ํ์ ๋ฐ ์์ ํ๋๋ฅผ ํ๋ฐ์ฑ์ผ๋ก ๋ง๋๋ ๊ฒ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ต๋๋ค. ์ฌ์ ํ ๋๊ธฐํ๊ฐ ํ์ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์กฐ๋ง๊ฐ ์ด์ด ์ข์ง ์์ ๊ฒ์ด๋ฉฐ ๋ถ์ ์ ํ ๊ฐ์ผ๋ก setLower() ๋ฐ setUpper()๋ฅผ ์ํํ๋ ๋ ๊ฐ์ ์ค๋ ๋๋ก ์ธํด ๋ฒ์๊ฐ ์ผ๊ด๋์ง ์์ ์ํ๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ด๊ธฐ ๊ฐ์ด (0, 5)์ด๊ณ ์ค๋ ๋ A๊ฐ setLower(4)๋ฅผ ํธ์ถํ๊ณ ๋์์ ์ค๋ ๋ B๊ฐ setUpper(3)๋ฅผ ํธ์ถํ๋ ๊ฒฝ์ฐ ์ด๋ฌํ ์ธํฐ๋ฆฌ๋ธ ์์
์ ๋ ๋ค ๊ฒ์ฌ๋ฅผ ํต๊ณผํ๋๋ผ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ๊ทธ๊ฒ์ ๋ถ๋ณ์ฑ์ ๋ณดํธํด์ผํฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ฒ์๋ (4, 3) - ์๋ชป๋ ๊ฐ์ด ๋ฉ๋๋ค. ๋ค๋ฅธ ๋ฒ์ ์์
์ ๋ํด setLower() ๋ฐ setUpper()๋ฅผ ์์์ ์ผ๋ก ๋ง๋ค์ด์ผ ํฉ๋๋ค. ํ๋๋ฅผ ํ๋ฐ์ฑ์ผ๋ก ๋ง๋ค๋ฉด ๊ทธ๋ ๊ฒ ๋์ง ์์ต๋๋ค.
์ฑ๋ฅ ๊ณ ๋ ค ์ฌํญ
ํ๋ฐ์ฑ์ ์ฌ์ฉํ๋ ์ฒซ ๋ฒ์งธ ์ด์ ๋ ๋จ์์ฑ์
๋๋ค. ์ด๋ค ์ํฉ์์๋ ๊ทธ๋ฌํ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ด๋ จ๋ ์ ๊ธ์ ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค ๋ ์ฝ์ต๋๋ค. ๋ ๋ฒ์งธ ์ด์ ๋ ์ฑ๋ฅ์
๋๋ค. ๋๋ก๋ ํ๋ฐ์ฑ์ด ์ ๊ธ๋ณด๋ค ๋น ๋ฅด๊ฒ ์๋ํฉ๋๋ค. ํนํ Java Virtual Machine์ ๋ด๋ถ ์์
๊ณผ ๊ด๋ จํ์ฌ "X๋ ํญ์ Y๋ณด๋ค ๋น ๋ฆ
๋๋ค"์ ๊ฐ์ ์ ํํ๊ณ ํฌ๊ด์ ์ธ ์ค๋ช
์ ์์ฑํ๋ ๊ฒ์ ๊ทนํ ์ด๋ ต์ต๋๋ค. (์๋ฅผ ๋ค์ด, JVM์ ์ผ๋ถ ์ํฉ์์ ์ ๊ธ์ ์์ ํ ํด์ ํ ์ ์์ผ๋ฏ๋ก ํ๋ฐ์ฑ ๋ ๋๊ธฐํ ๋น์ฉ์ ์ถ์์ ์ธ ๋ฐฉ์์ผ๋ก ๋
ผ์ํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค.) ๊ทธ๋ฌ๋ ๋๋ถ๋ถ์ ์ต์ ํ๋ก์ธ์ ์ํคํ
์ฒ์์ ํ๋ฐ์ฑ์ ์ฝ๋ ๋น์ฉ์ ์ผ๋ฐ ๋ณ์๋ฅผ ์ฝ๋ ๋น์ฉ๊ณผ ํฌ๊ฒ ๋ค๋ฅด์ง ์์ต๋๋ค. ํ๋ฐ์ฑ์ ์์ฑํ๋ ๋น์ฉ์ ๊ฐ์์ฑ์ ํ์ํ ๋ฉ๋ชจ๋ฆฌ ํ์ฑ์ผ๋ก ์ธํด ์ผ๋ฐ ๋ณ์๋ฅผ ์์ฑํ๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๋์ง๋ง ์ผ๋ฐ์ ์ผ๋ก ์ ๊ธ์ ์ค์ ํ๋ ๊ฒ๋ณด๋ค ์ ๋ ดํฉ๋๋ค.
ํ๋ฐ์ฑ์ ์ฌ๋ฐ๋ฅธ ์ฌ์ฉ์ ์ํ ํจํด
๋ง์ ๋์์ฑ ์ ๋ฌธ๊ฐ๋ค์ ํ๋ฐ์ฑ ๋ณ์๊ฐ ์ ๊ธ๋ณด๋ค ์ฌ๋ฐ๋ฅด๊ฒ ์ฌ์ฉํ๊ธฐ๊ฐ ๋ ์ด๋ ต๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ์ ํผํ๋ ๊ฒฝํฅ์ด ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฃผ์ ๊น๊ฒ ๋ฐ๋ฅด๋ฉด ๋ค์ํ ์ํฉ์์ ์์ ํ๊ฒ ์ฌ์ฉํ ์ ์๋ ๋ช ๊ฐ์ง ์ ์ ์๋ ํจํด์ด ์์ต๋๋ค. ํญ์ ํ๋ฐ์ฑ์ ํ๊ณ๋ฅผ ์กด์คํ์ญ์์ค. ํ๋ก๊ทธ๋จ์ ๋ค๋ฅธ ์ด๋ค ๊ฒ๊ณผ๋ ๋
๋ฆฝ์ ์ธ ํ๋ฐ์ฑ ๋ฌผ์ง๋ง ์ฌ์ฉํ์ญ์์ค. ์ด๋ ๊ฒ ํ๋ฉด ์ด๋ฌํ ํจํด์ผ๋ก ์ธํด ์ํํ ์์ญ์ ๋น ์ง๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
ํจํด #1: ์ํ ํ๋๊ทธ
์๋ง๋ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๋ณ์์ ์ ์ ์ฌ์ฉ์ ์ด๊ธฐํ ์๋ฃ ๋๋ ์ข
๋ฃ ์์ฒญ๊ณผ ๊ฐ์ ์ค์ํ ์ผํ์ฑ ์๋ช
์ฃผ๊ธฐ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์์ ๋ํ๋ด๋ ๊ฐ๋จํ ๋ถ์ธ ์ํ ํ๋๊ทธ์ผ ๊ฒ์
๋๋ค. ๋ง์ ์ ํ๋ฆฌ์ผ์ด์
์๋ ๋ชฉ๋ก 2์ ํ์๋ ๊ฒ์ฒ๋ผ "์ข
๋ฃํ ์ค๋น๊ฐ ๋ ๋๊น์ง ๊ณ์ ์คํ" ํ์์ ์ ์ด ๊ตฌ์ฑ์ด ํฌํจ๋์ด ์์ต๋๋ค.
volatile boolean shutdownRequested; ... public void shutdown() { shutdownRequested = true; } public void doWork() { while (!shutdownRequested) { // do stuff } }
shutdown() ๋ฉ์๋๋ ๋ฃจํ ์ธ๋ถ์ ๋ค๋ฅธ ์ค๋ ๋์์ ํธ์ถ๋ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค. ๋ฐ๋ผ์ ์ฌ๋ฐ๋ฅธ ๋ณ์ ๊ฐ์์ฑ shutdownRequested๋ฅผ ๋ณด์ฅํ๋ ค๋ฉด ๋๊ธฐํ๊ฐ ํ์ํฉ๋๋ค. (JMX ๋ฆฌ์ค๋, GUI ์ด๋ฒคํธ ์ค๋ ๋์ ์ก์
๋ฆฌ์ค๋, RMI, ์น ์๋น์ค ๋ฑ์ ํตํด ํธ์ถํ ์ ์์ต๋๋ค.) ๊ทธ๋ฌ๋ ๋๊ธฐํ๋ ๋ธ๋ก์ด ์๋ ๋ฃจํ๋ ๋ชฉ๋ก 2์ ๊ฐ์ด ํ๋ฐ์ฑ ์ํ ํ๋๊ทธ๊ฐ ์๋ ๋ฃจํ๋ณด๋ค ํจ์ฌ ๋ ๋ฒ๊ฑฐ๋กญ์ต๋๋ค. ํ๋ฐ์ฑ์ ์ฌ์ฉํ๋ฉด ์ฝ๋ ์์ฑ์ด ๋ ์ฌ์์ง๊ณ ์ํ ํ๋๊ทธ๊ฐ ๋ค๋ฅธ ํ๋ก๊ทธ๋จ ์ํ์ ์์กดํ์ง ์๊ธฐ ๋๋ฌธ์ ์ด๋ ๋ค์์ ์์
๋๋ค. ํ๋ฐ์ฑ์ ์ ์ฌ์ฉํฉ๋๋ค. ์ด๋ฌํ ์ํ ํ๋๊ทธ์ ํน์ง์ ์ผ๋ฐ์ ์ผ๋ก ์ํ ์ ํ์ด ํ๋๋ง ์๋ค๋ ๊ฒ์
๋๋ค. shutdownRequested ํ๋๊ทธ๊ฐ false์์ true๋ก ๋ฐ๋๊ณ ํ๋ก๊ทธ๋จ์ด ์ข
๋ฃ๋ฉ๋๋ค. ์ด ํจํด์ ์๋ค๋ก ๋ณ๊ฒฝ๋ ์ ์๋ ์ํ ํ๋๊ทธ๋ก ํ์ฅ๋ ์ ์์ง๋ง ์ธ๋ถ ๊ฐ์
์์ด ์ ํ ์ฃผ๊ธฐ(false์์ true, false๋ก)๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ์๋ง ๊ฐ๋ฅํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์์ ๋ณ์์ ๊ฐ์ ์ผ์ข
์ ์์ ์ ํ ๋ฉ์ปค๋์ฆ์ด ํ์ํฉ๋๋ค.
ํจํด #2: ์ผํ์ฑ ๋ณด์ ๊ฒ์
๋๊ธฐํ๊ฐ ์์ ๋ ๋ฐ์ํ ์ ์๋ ๊ฐ์์ฑ ์ค๋ฅ๋ ๊ธฐ๋ณธ ๊ฐ ๋์ ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ์์ฑํ ๋ ํจ์ฌ ๋ ์ด๋ ค์ด ๋ฌธ์ ๊ฐ ๋ ์ ์์ต๋๋ค. ๋๊ธฐํํ์ง ์์ผ๋ฉด ๋ค๋ฅธ ์ค๋ ๋์์ ์์ฑํ ๊ฐ์ฒด ์ฐธ์กฐ์ ํ์ฌ ๊ฐ์ ๋ณผ ์ ์์ผ๋ฉฐ ํด๋น ๊ฐ์ฒด์ ์ค๋๋ ์ํ ๊ฐ๋ ๊ณ์ ๋ณผ ์ ์์ต๋๋ค. (์ด ์ํ์ ๋๊ธฐํ ์์ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ์ฝ๋ ์
๋ช
๋์ ์ด์ค ํ์ธ ์ ๊ธ ๋ฌธ์ ์ ๊ทผ๋ณธ ์์ธ์
๋๋ค. ๊ทธ๋ฌ๋ฉด ์ค์ ์ฐธ์กฐ๋ฅผ ๋ณผ ์ ์์ง๋ง ์ด๋ฅผ ํตํด ๋ถ๋ถ์ ์ผ๋ก ๊ตฌ์ฑ๋ ๊ฐ์ฒด๋ฅผ ์ป์ ์ํ์ด ์์ต๋๋ค.) ๊ฐ์ฒด๋ ํ๋ฐ์ฑ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ๊ฒ์
๋๋ค. Listing 3์ ์์ํ๋ ๋์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ผ๋ถ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๋ ์๋ฅผ ๋ณด์ฌ์ค๋๋ค. ์ด ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ์๋ํ ์ ์๋ ๋ค๋ฅธ ์ฝ๋๋ ์ฌ์ฉ์ ์๋ํ๊ธฐ ์ ์ ํด๋น ๋ฐ์ดํฐ๊ฐ ๊ฒ์๋์๋์ง ํ์ธํฉ๋๋ค.
public class BackgroundFloobleLoader { public volatile Flooble theFlooble; public void initInBackground() { // ะดะตะปะฐะตะผ ะผะฝะพะณะพ ะฒััะบะพะณะพ theFlooble = new Flooble(); // ะตะดะธะฝััะฒะตะฝะฝะฐั ะทะฐะฟะธัั ะฒ theFlooble } } public class SomeOtherClass { public void doWork() { while (true) { // ัั-ัะพ ัะฐะผ ะดะตะปะฐะตะผ... // ะธัะฟะพะปัะทัะตะผ theFolooble, ะฝะพ ัะพะปัะบะพ ะตัะปะธ ะพะฝะฐ ะณะพัะพะฒะฐ if (floobleLoader.theFlooble != null) doSomething(floobleLoader.theFlooble); } } }
theFooble์ ๋ํ ์ฐธ์กฐ๊ฐ ์ผ์์ ์ด์ง ์์ ๊ฒฝ์ฐ doWork()์ ์ฝ๋๋ theFlooble์ ์ฐธ์กฐํ๋ ค๊ณ ํ ๋ ๋ถ๋ถ์ ์ผ๋ก ์์ฑ๋ Flooble์ ๋ณผ ์ํ์ด ์์ต๋๋ค. ์ด ํจํด์ ํต์ฌ ์๊ตฌ ์ฌํญ์ ๊ฒ์๋ ๊ฐ์ฒด๊ฐ ์ค๋ ๋๋ก๋ถํฐ ์์ ํ๊ฑฐ๋ ์ฌ์ค์ ๋ถ๋ณ์ด์ด์ผ ํ๋ค๋ ๊ฒ์
๋๋ค. ์ฆ, ๋ถ๋ณ์ด๋ ๊ฒ์๋ ํ ์ํ๊ฐ ์ ๋ ๋ณ๊ฒฝ๋์ง ์๋๋ค๋ ์๋ฏธ์
๋๋ค. ํ๋ฐ์ฑ ๋งํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ฒด๊ฐ ๊ฒ์๋ ํ์์ผ๋ก ํ์๋๋๋ก ํ ์ ์์ง๋ง ๊ฒ์ ํ ๊ฐ์ฒด์ ์ํ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์ถ๊ฐ ๋๊ธฐํ๊ฐ ํ์ํฉ๋๋ค.
ํจํด #3: ๋
๋ฆฝ์ ์ธ ๊ด์ฐฐ
ํ๋ฐ์ฑ์ ์์ ํ๊ฒ ์ฌ์ฉํ๋ ๋ ๋ค๋ฅธ ๊ฐ๋จํ ์๋ ๊ด์ฐฐ ๊ฒฐ๊ณผ๊ฐ ํ๋ก๊ทธ๋จ ๋ด์์ ์ฌ์ฉํ๊ธฐ ์ํด ์ฃผ๊ธฐ์ ์ผ๋ก "๊ฒ์"๋๋ ๊ฒฝ์ฐ์
๋๋ค. ์๋ฅผ ๋ค์ด, ํ์ฌ ์จ๋๋ฅผ ๊ฐ์งํ๋ ํ๊ฒฝ ์ผ์๊ฐ ์์ต๋๋ค. ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋๋ ๋ช ์ด๋ง๋ค ์ด ์ผ์๋ฅผ ์ฝ๊ณ ํ์ฌ ์จ๋๊ฐ ํฌํจ๋ ํ๋ฐ์ฑ ๋ณ์๋ฅผ ์
๋ฐ์ดํธํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ฉด ๋ค๋ฅธ ์ค๋ ๋๋ ์ด ๋ณ์๋ฅผ ์ฝ์ ์ ์์ผ๋ฉฐ ๊ทธ ๊ฐ์ด ํญ์ ์ต์ ์์ ์ ์ ์์ต๋๋ค. ์ด ํจํด์ ๋ ๋ค๋ฅธ ์ฉ๋๋ ํ๋ก๊ทธ๋จ์ ๋ํ ํต๊ณ๋ฅผ ์์งํ๋ ๊ฒ์
๋๋ค. ๋ชฉ๋ก 4๋ ์ธ์ฆ ๋ฉ์ปค๋์ฆ์ด ๋ง์ง๋ง์ผ๋ก ๋ก๊ทธ์ธํ ์ฌ์ฉ์์ ์ด๋ฆ์ ๊ธฐ์ตํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค. lastUser ์ฐธ์กฐ๋ ํ๋ก๊ทธ๋จ์ ๋๋จธ์ง ๋ถ๋ถ์์ ์ฌ์ฉํ ๊ฐ์ ๊ฒ์ํ๋ ๋ฐ ์ฌ์ฌ์ฉ๋ฉ๋๋ค.
public class UserManager { public volatile String lastUser; public boolean authenticate(String user, String password) { boolean valid = passwordIsValid(user, password); if (valid) { User u = new User(); activeUsers.add(u); lastUser = user; } return valid; } }
์ด ํจํด์ ์ด์ ํจํด์ ํ์ฅํฉ๋๋ค. ๊ฐ์ ํ๋ก๊ทธ๋จ์ ๋ค๋ฅธ ๊ณณ์์ ์ฌ์ฉํ๊ธฐ ์ํด ๊ฒ์๋์ง๋ง ๊ฒ์๋ ์ผํ์ฑ ์ด๋ฒคํธ๊ฐ ์๋๋ผ ์ผ๋ จ์ ๋
๋ฆฝ์ ์ธ ์ด๋ฒคํธ์
๋๋ค. ์ด ํจํด์ ์ฌ์ฉํ๋ ค๋ฉด ๊ฒ์๋ ๊ฐ์ด ํจ๊ณผ์ ์ผ๋ก ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํด์ผ ํฉ๋๋ค. ์ฆ, ๊ฒ์ ํ์ ์ํ๊ฐ ๋ณ๊ฒฝ๋์ง ์์์ผ ํฉ๋๋ค. ๊ฐ์ ์ฌ์ฉํ๋ ์ฝ๋๋ ์ธ์ ๋ ์ง ๋ณ๊ฒฝ๋ ์ ์๋ค๋ ์ ์ ์ธ์ํด์ผ ํฉ๋๋ค.
ํจํด #4: "ํ๋ฐ์ฑ ์ฝฉ" ํจํด
"ํ๋ฐ์ฑ ๋น" ํจํด์ JavaBeans๋ฅผ "์๊ดํ๋ ๊ตฌ์กฐ์ฒด"๋ก ์ฌ์ฉํ๋ ํ๋ ์์ํฌ์ ์ ์ฉ ๊ฐ๋ฅํฉ๋๋ค. "ํ๋ฐ์ฑ ๋น" ํจํด์ getter ๋ฐ/๋๋ setter๊ฐ ์๋ ๋
๋ฆฝ์ ์ธ ์์ฑ ๊ทธ๋ฃน์ ๋ํ ์ปจํ
์ด๋๋ก JavaBean์ ์ฌ์ฉํฉ๋๋ค. "ํ๋ฐ์ฑ ๋น" ํจํด์ ์ด๋ก ์ ๊ทผ๊ฑฐ๋ ๋ง์ ํ๋ ์์ํฌ๊ฐ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๋ฐ์ดํฐ ํ๋(์: HttpSession)์ ๋ํ ์ปจํ
์ด๋๋ฅผ ์ ๊ณตํ์ง๋ง ์ด๋ฌํ ์ปจํ
์ด๋์ ๋ฐฐ์น๋ ๊ฐ์ฒด๋ ์ค๋ ๋๋ก๋ถํฐ ์์ ํด์ผ ํ๋ค๋ ๊ฒ์
๋๋ค. ํ๋ฐ์ฑ ๋น ํจํด์์ ๋ชจ๋ JavaBean ๋ฐ์ดํฐ ์์๋ ํ๋ฐ์ฑ์ด๋ฉฐ getter ๋ฐ setter๋ ๊ฐ๋จํด์ผ ํฉ๋๋ค. ํด๋น ์์ฑ์ ๊ฐ์ ธ์ค๊ฑฐ๋ ์ค์ ํ๋ ๊ฒ ์ด์ธ์ ๋
ผ๋ฆฌ๋ฅผ ํฌํจํด์๋ ์ ๋ฉ๋๋ค. ๋ํ ๊ฐ์ฒด ์ฐธ์กฐ์ธ ๋ฐ์ดํฐ ๋ฉค๋ฒ์ ๊ฒฝ์ฐ ํด๋น ๊ฐ์ฒด๋ ์ฌ์ค์ ๋ถ๋ณ์ด์ด์ผ ํฉ๋๋ค. (๋ฐฐ์ด ์ฐธ์กฐ๊ฐ ํ๋ฐ์ฑ์ผ๋ก ์ ์ธ๋๋ฉด ์์ ์์ฒด๊ฐ ์๋ ํด๋น ์ฐธ์กฐ๋ง ํ๋ฐ์ฑ ์์ฑ์ ๊ฐ๊ธฐ ๋๋ฌธ์ ๋ฐฐ์ด ์ฐธ์กฐ ํ๋๋ฅผ ํ์ฉํ์ง ์์ต๋๋ค.) ๋ชจ๋ ํ๋ฐ์ฑ ๋ณ์์ ๋ง์ฐฌ๊ฐ์ง๋ก JavaBeans์ ์์ฑ๊ณผ ๊ด๋ จ๋ ๋ถ๋ณ์ด๋ ์ ํ์ด ์์ ์ ์์ต๋๋ค. . "ํ๋ฐ์ฑ ๋น" ํจํด์ ์ฌ์ฉํ์ฌ ์์ฑ๋ JavaBean์ ์๊ฐ ๋ชฉ๋ก 5์ ํ์๋์ด ์์ต๋๋ค.
@ThreadSafe public class Person { private volatile String firstName; private volatile String lastName; private volatile int age; public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public int getAge() { return age; } public void setFirstName(String firstName) { this.firstName = firstName; } public void setLastName(String lastName) { this.lastName = lastName; } public void setAge(int age) { this.age = age; } }
๋์ฑ ๋ณต์กํ ํ๋ฐ์ฑ ํจํด
์ด์ ์น์
์ ํจํด์ ํ๋ฐ์ฑ ์ฌ์ฉ์ด ํฉ๋ฆฌ์ ์ด๊ณ ๋ถ๋ช
ํ ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ์ ๋๋ถ๋ถ์ ๋ค๋ฃน๋๋ค. ์ด ์น์
์์๋ ํ๋ฐ์ฑ์ด ์ฑ๋ฅ์ด๋ ํ์ฅ์ฑ ์ด์ ์ ์ ๊ณตํ ์ ์๋ ๋ณด๋ค ๋ณต์กํ ํจํด์ ์ดํด๋ด
๋๋ค. ๋ณด๋ค ๋ฐ์ ๋ ํ๋ฐ์ฑ ํจํด์ ๋งค์ฐ ์ทจ์ฝํ ์ ์์ต๋๋ค. ๊ฐ์ ์ ์ฃผ์ ๊น๊ฒ ๋ฌธ์ํํ๊ณ ์ด๋ฌํ ํจํด์ ๊ฐ๋ ฅํ๊ฒ ์บก์ํํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์์ฃผ ์์ ๋ณ๊ฒฝ์ด๋ผ๋ ์ฝ๋๋ฅผ ์์์ํฌ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค! ๋ํ ๋ ๋ณต์กํ ํ๋ฐ์ฑ ์ฌ์ฉ ์ฌ๋ก์ ์ฃผ๋ ์ด์ ๋ ์ฑ๋ฅ์ด๋ฏ๋ก ์ด๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ์ค์ ๋ก ์๋ํ ์ฑ๋ฅ ํฅ์์ ๋ํ ๋ช
ํํ ํ์์ฑ์ด ์๋์ง ํ์ธํ์ญ์์ค. ์ด๋ฌํ ํจํด์ ๊ฐ๋ฅํ ์ฑ๋ฅ ํฅ์์ ์ํด ๊ฐ๋
์ฑ์ด๋ ์ ์ง ๊ด๋ฆฌ ์ฉ์ด์ฑ์ ํฌ์ํ๋ ์ ์ถฉ์์
๋๋ค. ์ฑ๋ฅ ํฅ์์ด ํ์ํ์ง ์๊ฑฐ๋ ์๊ฒฉํ ์ธก์ ํ๋ก๊ทธ๋จ์ผ๋ก ํ์ํ๋ค๋ ๊ฒ์ ์ฆ๋ช
ํ ์ ์๋ค๋ฉด ์๋ง๋ ๋์ ๊ฑฐ๋์ผ ๊ฒ์
๋๋ค. ๋น์ ์ ๊ฐ์น ์๋ ๊ฒ์ ํฌ๊ธฐํ๊ณ ๊ทธ ๋๊ฐ๋ก ๋ ์ ์ ๊ฒ์ ์ป๊ณ ์์ต๋๋ค.
ํจํด #5: ์ ๋ ดํ ์ฝ๊ธฐ-์ฐ๊ธฐ ์ ๊ธ
์ง๊ธ์ฏค์ด๋ฉด ํ๋ฐ์ฑ์ด ์นด์ดํฐ๋ฅผ ๊ตฌํํ๊ธฐ์๋ ๋๋ฌด ์ฝํ๋ค๋ ๊ฒ์ ์ ์๊ณ ๊ณ์ค ๊ฒ์
๋๋ค. ++x๋ ๋ณธ์ง์ ์ผ๋ก ์ธ ๊ฐ์ง ์์
(์ฝ๊ธฐ, ์ถ๊ฐ, ์ ์ฅ)์ ์ค์ฌ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ๊ฒฝ์ฐ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ํ๋ฐ์ฑ ์นด์ดํฐ๋ฅผ ์ฆ๊ฐ์ํค๋ ค๊ณ ํ๋ฉด ์
๋ฐ์ดํธ๋ ๊ฐ์ ์๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ณ๊ฒฝ ์ฌํญ๋ณด๋ค ์ฝ๊ธฐ ํ์๊ฐ ํจ์ฌ ๋ ๋ง์ ๊ฒฝ์ฐ์๋ ๋ด์ฅ ์ ๊ธ ๋ฐ ํ๋ฐ์ฑ ๋ณ์๋ฅผ ๊ฒฐํฉํ์ฌ ์ ์ฒด ์ฝ๋ ๊ฒฝ๋ก ์ค๋ฒํค๋๋ฅผ ์ค์ผ ์ ์์ต๋๋ค. Listing 6์์๋ ๋๊ธฐํ๋ฅผ ์ฌ์ฉํ์ฌ ์ฆ๋ถ ์์
์ด ์์์ฑ์ธ์ง ํ์ธํ๊ณ ํ๋ฐ์ฑ์ ์ฌ์ฉํ์ฌ ํ์ฌ ๊ฒฐ๊ณผ๊ฐ ํ์๋๋์ง ํ์ธํ๋ ์ค๋ ๋๋ก๋ถํฐ ์์ ํ ์นด์ดํฐ๋ฅผ ๋ณด์ฌ์ค๋๋ค. ์
๋ฐ์ดํธ๊ฐ ์์ฃผ ๋ฐ์ํ์ง ์๋ ๊ฒฝ์ฐ ์ฝ๊ธฐ ๋น์ฉ์ด ์ผ์์ ์ธ ์ฝ๊ธฐ๋ก ์ ํ๋๋ฏ๋ก ์ผ๋ฐ์ ์ผ๋ก ์ถฉ๋ํ์ง ์๋ ์ ๊ธ์ ํ๋ํ๋ ๊ฒ๋ณด๋ค ์ ๋ ดํ๋ฏ๋ก ์ด ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ์ด ํฅ์๋ ์ ์์ต๋๋ค.
@ThreadSafe public class CheesyCounter { // Employs the cheap read-write lock trick // All mutative operations MUST be done with the 'this' lock held @GuardedBy("this") private volatile int value; public int getValue() { return value; } public synchronized int increment() { return value++; } }
์ด ๋ฐฉ๋ฒ์ "์ ๋ ดํ ์ฝ๊ธฐ-์ฐ๊ธฐ ์ ๊ธ"์ด๋ผ๊ณ ๋ถ๋ฅด๋ ์ด์ ๋ ์ฝ๊ธฐ์ ์ฐ๊ธฐ์ ์๋ก ๋ค๋ฅธ ํ์ด๋ฐ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์
๋๋ค. ์ด ๊ฒฝ์ฐ ์ฐ๊ธฐ ์์
์ ํ๋ฐ์ฑ ์ฌ์ฉ์ ์ฒซ ๋ฒ์งธ ์กฐ๊ฑด์ ์๋ฐํ๋ฏ๋ก ํ๋ฐ์ฑ์ ์ฌ์ฉํ์ฌ ์นด์ดํฐ๋ฅผ ์์ ํ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค. ์ ๊ธ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ํ๋ฐ์ฑ์ ์ฌ์ฉํ์ฌ ์ฝ์ ๋ ํ์ฌ ๊ฐ์ ํ์ํ ์ ์์ผ๋ฏ๋ก ๋ชจ๋ ์์ ์์
์๋ ์ ๊ธ์ ์ฌ์ฉํ๊ณ ์ฝ๊ธฐ ์ ์ฉ ์์
์๋ ํ๋ฐ์ฑ์ ์ฌ์ฉํฉ๋๋ค. ์ ๊ธ์ด ํ ๋ฒ์ ํ๋์ ์ค๋ ๋๋ง ๊ฐ์ ์ก์ธ์คํ๋๋ก ํ์ฉํ๋ ๊ฒฝ์ฐ ํ๋ฐ์ฑ ์ฝ๊ธฐ๋ ๋ ์ด์์ ์ฝ๊ธฐ๋ฅผ ํ์ฉํ๋ฏ๋ก ์ฝ๊ธฐ๋ฅผ ๋ณดํธํ๊ธฐ ์ํด ํ๋ฐ์ฑ์ ์ฌ์ฉํ๋ฉด ๋ชจ๋ ์ฝ๋์ ์ ๊ธ์ ์ฌ์ฉํ ๋๋ณด๋ค ๋ ๋์ ์์ค์ ๊ตํ์ ์ป์ ์ ์์ต๋๋ค. ์ฝ๊ณ ๊ธฐ๋กํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด ํจํด์ ์ทจ์ฝ์ฑ์ ์ ์ํ์ญ์์ค. ๋ ๊ฐ์ง ๊ฒฝ์ ๋๊ธฐํ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ๋ฉด ์ด ํจํด์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ์ ์ฉ ๋ฒ์๋ฅผ ๋์ด์๋ฉด ๋งค์ฐ ๋ณต์กํด์ง ์ ์์ต๋๋ค.
์์ฝ
ํ๋ฐ์ฑ ๋ณ์๋ ์ ๊ธ๋ณด๋ค ๊ฐ๋จํ์ง๋ง ์ฝํ ํํ์ ๋๊ธฐํ๋ก, ์ด๋ค ๊ฒฝ์ฐ์๋ ๋ด์ฅ ์ ๊ธ๋ณด๋ค ๋ ๋์ ์ฑ๋ฅ์ด๋ ํ์ฅ์ฑ์ ์ ๊ณตํฉ๋๋ค. ํ๋ฐ์ฑ์ ์์ ํ ์ฌ์ฉ์ ์ํ ์กฐ๊ฑด์ ์ถฉ์กฑํ๋ ๊ฒฝ์ฐ(๋ณ์๋ ๋ค๋ฅธ ๋ณ์ ๋ฐ ์ด์ ๊ฐ ๋ชจ๋์ ์ค์ ๋ก ๋
๋ฆฝ์ ์
๋๋ค) ๋๋๋ก ๋๊ธฐํ๋ฅผ ํ๋ฐ์ฑ์ผ๋ก ๋์ฒดํ์ฌ ์ฝ๋๋ฅผ ๋จ์ํํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ํ๋ฐ์ฑ์ ์ฌ์ฉํ๋ ์ฝ๋๋ ์ ๊ธ์ ์ฌ์ฉํ๋ ์ฝ๋๋ณด๋ค ์ทจ์ฝํ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ์ฌ๊ธฐ์ ์ ์๋ ํจํด์ ๋ณ๋์ฑ์ด ๋๊ธฐํ์ ๋ํ ํฉ๋ฆฌ์ ์ธ ๋์์ธ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ๋ฅผ ๋ค๋ฃน๋๋ค. ์ด๋ฌํ ํจํด์ ๋ฐ๋ฅด๊ณ ํ๊ณ๋ฅผ ์ด๊ณผํ์ง ์๋๋ก ์ฃผ์ํจ์ผ๋ก์จ ์ด์ ์ ์ ๊ณตํ๋ ๊ฒฝ์ฐ ํ๋ฐ์ฑ์ ์์ ํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
GO TO FULL VERSION