Open stemmmm opened 2 months ago
동시성과 같은 환경에서 예상치 못한 문제를 방지하거나, 데이터의 무결성을 유지하기 위해서
[데이터 무결성]
[데드락]
var flag: Bool = false
let thread1 = Thread {
flag = true
}
let thread2 = Thread {
if flag {
print("플래그가 참입니다.")
}
}
thread1.start()
thread2.start()
thread2
는 flag
의 상태를 가정하고 작업을 수행하는데, 메모리 가시성에 의해 반영되지 않은 flag
에 접근한다면 예상치 못한 결과를 얻게 될 것입니다.[CPU 캐시 사용] 각 CPU 코어는 메인 메모리에 직접 접근하는 대신, 캐시를 통해 성능을 향상시킵니다. 스레드가 메모리에 접근하면, CPU는 그 값을 메인 메모리가 아닌 캐시에 저장한 후 해당 값을 사용하는 것이죠.
하지만 CPU 코어는 자신의 로컬 캐시를 사용하기 때문에 다른 코어에서 실행 중인 스레드가 변경한 값이 즉시 반영되지 않을 수 있습니다.
[메모리 버퍼링] CPU가 성능을 최적화하기 위해 쓰기 버퍼를 사용하면, 메모리 가시성 문제가 발생할 수 있습니다. 쓰기 버퍼는 메모리로 직접 데이터를 쓰지 않고, 일시적으로 저장해두었다가 나중에 한번에 메모리에 쓰기 작업을 수행하는 것입니다. 이는 다른 스레드가 해당 값에 접근할 때, 최신 값이 아닌 이전 값을 읽을 가능성이 생깁니다.
volatile
키워드 사용
var sharedCount = 0
let group = DispatchGroup()
DispatchQueue.global().async(group: group) {
for _ in 1...1000 {
sharedCount += 1
}
}
DispatchQueue.global().async(group: group) {
for _ in 1...1000 {
sharedCount += 1
}
}
DispatchQueue.global().async(group: group) {
for _ in 1...1000 {
sharedCount += 1
}
}
group.notify(queue: .main) {
print(sharedCount)
}
let group = DispatchGroup()
let semaphore = DispatchSemaphore(value: 1)
var sharedCount = 0
DispatchQueue.global().async(group: group) {
semaphore.wait()
for _ in 1...1000 {
sharedCount += 1
}
semaphore.signal()
}
DispatchQueue.global().async(group: group) {
semaphore.wait()
for _ in 1...1000 {
sharedCount += 1
}
semaphore.signal()
}
DispatchQueue.global().async(group: group) {
semaphore.wait()
for _ in 1...1000 {
sharedCount += 1
}
semaphore.signal()
}
group.notify(queue: .main) {
print(sharedCount)
}