Skip to content

๐Ÿ™‹โ€โ™‚๏ธactor

Tltlbo edited this page Dec 2, 2024 · 2 revisions
class Counter {
	var count = 0
	
	func increase() {
		count += 1
	}
}

๊ฐ๊ธฐ ๋‹ค๋ฅธ ๊ณณ์—์„œ ๋™์ผํ•œ Counter ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜์—ฌ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ ‘๊ทผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž.

increase() ๊ฐ€ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ๋™์ž‘ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค๋ฉด,

๋‚ด๋ถ€์˜ count ํ”„๋กœํผํ‹ฐ๋Š” dataRace ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ณ , ๋ณ€๊ฒฝ์ด ๊ฐ€๋Šฅํ•œ ์ƒํƒœ(shared mutable state) ์ด๊ธฐ ๋•Œ๋ฌธ.

๋งŒ์•ฝ ๊ตฌ์กฐ์ฒด๋ผ๋ฉด?

struct Counter {
	var count = 0
	
	mutating func increase() {
		count += 1
	}
}

๊ทธ๋ž˜๋„ DispatchQueue.global ์„ ์ด์šฉํ•ด์„œ ๋น„๋™๊ธฐ์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋ฉด dataRace ๋ฐœ์ƒ.

๊ฒฐ๊ตญ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด let ์œผ๋กœ, ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค.

๋‹ค๋งŒ ๊ทธ๊ฑด ์‹ซ์Œ.

Actor

  • class์™€ ์œ ์‚ฌํ•œ ์ƒˆ๋กœ์šด ํƒ€์ž…
  • ํ”„๋กœํผํ‹ฐ, ๋ฉ”์„œ๋“œ, ์ด๋‹ˆ์…œ๋ผ์ด์ € ๋“ฑ๋“ฑ์„ ๋ชจ๋‘ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Œ.
  • ํ”„๋กœํ† ์ฝœ, extension๋„ ๊ฐ€๋Šฅ
  • ์ฐธ์กฐํƒ€์ž…
  • ์ƒ์† ์ง€์› x

ํŠน์ง•

actor ๋‚ด๋ถ€์˜ ๊ฐ’์— ๋™์‹œ์— ์ ‘๊ทผ๋˜์ง€ ์•Š๋„๋ก ๋ณด์žฅํ•จ.

actor Counter {
	var count: Int = 0
	
	func increase() {
		count += 1
	}
}

//์™ธ๋ถ€
let counter = Counter()
await counter.increase()

์ด๋Ÿฐ ์‹์œผ๋กœ actor ๋‚ด๋ถ€์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ๋‚ด๋ถ€์˜ ๊ฐ’์„ ๋ณ€๊ฒฝ์‹œํ‚ฌ ๋•Œ,

์™ธ๋ถ€์—์„œ ํ˜ธ์ถœ ์‹œ, ์ž ์‹œ๋™์•ˆ ํ˜ธ์ถœ์ฝ”๋“œ๋ฅผ โ€œ๊ธฐ๋‹ค๋ฆฌ๊ฒŒโ€ ๋งŒ๋“ ๋‹ค.

๊ทธ๋ฆฌ๊ณ  actor๋Š” ๋ฐ์ดํ„ฐ๋ ˆ์ด์Šค๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์„ ์‹œ์ ์— ์•Œ์•„์„œ ํ˜ธ์ถœ์ฝ”๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.

actor ๋‚ด๋ถ€์˜ ํ”„๋กœํผํ‹ฐ์˜ ์ ‘๊ทผ์€ ๋ฌด์กฐ๊ฑด self๋กœ๋งŒ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

actor Counter {
	var count: Int = 0
	
	func increase(diffCounter: Counter) {
		self.count += 1
		diffCounter.count += 1 ๐Ÿšจ ์—๋Ÿฌ ๋ฐœ์ƒ!
	}
}

actor ๋‚ด๋ถ€์— ์ •์˜๋œ ํ”„๋กœํผํ‹ฐ, instance ๋ฉ”์„œ๋“œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ, actor-isolated ์ƒํƒœ.

actor-isolated ์ธ ์• ๋“ค์€ ๋ฌด์กฐ๊ฑด self๋กœ ์ ‘๊ทผ๋˜์–ด์•ผ ํ•œ๋‹ค.

actor Counter {
	var count: Int = 0
	let name: String = "hello"
	
	func increase(diffCounter: Counter) {
		self.count += 1
		print(diffCounter.name)
	}
}

๋‹ค๋งŒ ํ”„๋กœํผํ‹ฐ๊ฐ€ ๋ถˆ๋ณ€ ์ƒํƒœ ์ผ ๊ฒฝ์šฐ์—๋Š” ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. (cross-actor reference)

๋‹จ, ๋‹ค๋ฅธ ๋ชจ๋“ˆ์—์„œ๋Š” ๋ถˆ๊ฐ€ํ•˜๋‹ค.

๋‹ค๋ฅธ ๋ชจ๋“ˆ์—์„œ ์ ‘๊ทผํ•˜๋ ค๋ฉด ๋ฌด์กฐ๊ฑด ์•„๊นŒ๋ณด์•˜๋˜ await์„ ์ด์šฉํ•œ ๋น„๋™๊ธฐ๋กœ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•œ๋‹ค.

์ด์œ ๋Š” Counter๋ฅผ ์ •์˜ํ•œ ๋ชจ๋“ˆ์—์„œ ๋ชจ์ข…์˜ ์ด์œ ๋กœ name์ด var๋กœ ๋ณ€๊ฒฝ๋  ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค.

actor ๋‚ด๋ถ€์—์„œ๋Š” ๋™๊ธฐ์ , ์™ธ๋ถ€์—์„œ๋Š” ๋น„๋™๊ธฐ์ 

actor Counter {
	var count: Int = 0
	let name: String = "hello"
	
	func increase(diffCounter: Counter) {
		self.count += 1
		await diffCounter.decrease()
	}
}

extension Counter {
	func decrease() {
		self.count -= 1
	}
}

์ด๋Ÿฐ ์‹์œผ๋กœ ์ž์‹ ์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋Š” ๋™๊ธฐ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋‚˜, ์™ธ๋ถ€์—์„œ ์ด๋ฅผ ํ˜ธ์ถœ ์‹œ, await์„ ์ด์šฉํ•ด ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ ‘๊ทผํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ค€๋‹ค.

์ด๋•Œ, ๋ฉ”์„œ๋“œ์— ๋”ฐ๋กœ async ํ‚ค์›Œ๋“œ๋ฅผ ๋‹ฌ์•„์ฃผ์ง€ ์•Š๋”๋ผ๋„, ์•Œ์•„์„œ ์ž˜ํ•ด์ค€๋‹ค.

isolated

๋งŒ์•ฝ Counter๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๋Š” ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค๊ณ  ์น˜์ž.

func double(counter: Counter) {
	counter.count *= 2
}

๋‹น์—ฐํžˆ ์ด ์ฝ”๋“œ๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. counter์˜ count๋Š” actor-isolated ํ”„๋กœํผํ‹ฐ๋ผ ์™ธ๋ถ€์—์„œ ์ฐธ์กฐ ๋  ์ˆ˜ ์—†๋‹ค.

์ด๊ฑธ ํ•ด๊ฒฐ ํ•˜๋ ค๋ฉด double ํ•จ์ˆ˜๊ฐ€ actor-isolated ํ•จ์ˆ˜๊ฐ€ ๋˜์–ด์ฃผ๋ฉด ๋œ๋‹ค.

how?

๋ฐฉ๋ฒ•์€ ๊ฐ„๋‹จํ•˜๋‹ค.

func double(isolated counter: Counter) {
	counter.count *= 2
}

์ด๋Ÿฐ ์‹์œผ๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ isolated ํ‚ค์›Œ๋“œ๋ฅผ ๋„ฃ์–ด์คŒ์œผ๋กœ์จ double ํ•จ์ˆ˜๋Š” isolated Context๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋œ๋‹ค.

nonisolated

๊ธฐ์กด actor ๋‚ด๋ถ€์˜ ๊ฐ’์— ์ ‘๊ทผํ•˜๋ ค๋ฉด await ํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ ๋ ˆ์ด์Šค๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์„ ์‹œ์ ์— ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ์—ˆ๋‹ค.(๋น„๋™๊ธฐ)

ํ•˜์ง€๋งŒ ์ด๊ฑธ ๋™๊ธฐ์ ์œผ๋กœ ์ฐธ์กฐํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค๋ฉด, nonisolated ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

actor Counter {
	var count: Int = 0
	nonisolated let name: String = "hello"
	
	func increase(diffCounter: Counter) {
		self.count += 1
		await diffCounter.decrease()
	}
}

extension Counter {
	func decrease() {
		self.count -= 1
	}
}

//๊ธฐ์กด
let name = await Counter.name
//nonisolated ์ ์šฉ ์‹œ
let name = Counter.name
print(name)

์ด๋Ÿฐ ์‹์œผ๋กœ await์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ๋™๊ธฐ์  ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

๋‹ค๋งŒ var ์— ์ ์šฉ ์‹œ์—๋Š” ๋ถˆ๊ฐ€ํ•˜๋‹ค. ๋‹น์—ฐํ•˜๋‹ค. data race๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

let์˜ ๊ฒฝ์šฐ ์ฝ์œผ๋ฉด ๊ทธ๋งŒ์ด์ง€๋งŒ var์˜ ๊ฒฝ์šฐ ์ˆ˜์ •๋„ ๊ฐ€๋Šฅํ•ด์ ธ ๋ฒ„๋ ค data race ๋ฅผ ๋ง‰์„ ์ˆ˜ ์—†๊ฒŒ ๋œ๋‹ค.

iOS07 ํ”„๋กœ์ ํŠธ ์ผ์ง€

๐Ÿ“š ๋ฌธ์„œ

๐Ÿซถ๐Ÿป ํŒ€ ๊ธฐ๋ก

๐ŸŽค ํ”„๋กœ์ ํŠธ

๐Ÿ’ก ํ•ต์‹ฌ ๊ฒฝํ—˜

๐Ÿšจ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…

๐Ÿ“” ํ•™์Šต ์ •๋ฆฌ

๐Ÿช„ QA

Clone this wiki locally