A race condition occurs when two threads access a shared variable at the same time.
The first thread reads the variable, and the second thread reads the same value from the variable. Then the first thread and second thread perform their operations on the value, and they race to see which thread can write the value last to the shared variable. The value of the thread that writes its value last is preserved, because the thread is writing over the value that the previous thread wrote.
공학 분야에서 경쟁 상태(race condition)란 둘 이상의 입력 또는 조작의 타이밍이나 순서 등이 결과값에 영향을 줄 수 있는 상태를 말한다. 입력 변화의 타이밍이나 순서가 예상과 다르게 작동하면 정상적인 결과가 나오지 않게 될 위험이 있는데 이를 경쟁 위험이라고 한다.
Race conditions and deadlocks - Visual Basic
A deadlock occurs when two threads each lock a different variable at the same time and then try to lock the variable that the other thread already locked.
As a result, each thread stops executing and waits for the other thread to release the variable. Because each thread is holding the variable that the other thread wants, nothing occurs, and the threads remain deadlocked.
교착 상태(膠着狀態, 영어: deadlock)란 두 개 이상의 작업이 서로 상대방의 작업이 끝나기 만을 기다리고 있기 때문에 결과적으로 아무것도 완료되지 못하는 상태를 가리킨다. 예를 들어 하나의 사다리가 있고, 두 명의 사람이 각각 사다리의 위쪽과 아래쪽에 있다고 가정한다. 이때 아래에 있는 사람은 위로 올라 가려고 하고, 위에 있는 사람은 아래로 내려오려고 한다면, 두 사람은 서로 상대방이 사다리에서 비켜줄 때까지 하염없이 기다리고 있을 것이고 결과적으로 아무도 사다리를 내려오거나 올라가지 못하게 되듯이, 전산학에서 교착 상태란 다중 프로그래밍 환경에서 흔히 발생할 수 있는 문제이다. 이 문제를 해결하는 일반적인 방법은 아직 없는 상태이다.
메모리 할당은 값 타입과 참조 타입의 가장 눈에 띄는 차이점입니다. 앞서 설명했듯이 값 타입과 참조 타입은 각각 메모리의 스택과 힙 영역에 할당됩니다. 스택 영역에 할당되는 것은 스택 할당(Stack allocation), 힙 영역에 할당되는 것은 힙 할당(Heap allocation)이라고 부르겠습니다.
스택 할당과 힙 할당에는 구조적인 차이가 있습니다.
어떤 처리를 하기 위해 들어가는 간접적인 처리 시간 · 메모리 등을 말한다.
예를 들어 A라는 처리를 단순하게 실행한다면 10초 걸리는데, 안전성을 고려하고 부가적인 B라는 처리를 추가한 결과 처리시간이 15초 걸렸다면, 오버헤드는 5초가 된다. 또한 이 처리 B를 개선해 B'라는 처리를 한 결과, 처리시간이 12초가 되었다면, 이 경우 오버헤드가 3초 단축되었다고 말한다
In computer science, overhead is any combination of excess or indirect computation time, memory, bandwidth, or other resources that are required to perform a specific task.
앞서 값 타입을 복사하면 각각의 인스턴스는 유일한 복사값을 가지게 된다고 언급하였습니다. 하지만 항상 그렇지는 않습니다. 스위프트에서는 효율적으로 자원을 관리하기 위해 Copy-on-Write라는 기술을 사용하여 인스턴스의 불필요한 복사를 줄입니다.
Copy-on-Write의 기본 원리는 다음과 같습니다.
인스턴스를 복사할 때 먼저 참조를 통해 불필요한 복사를 줄이고, 수정이 발생하는 경우에만 실제로 복사를 하는 방식
줄여서 COW라고 간단하게 표현합니다. 스위프트에서는 기본적으로 Collection
타입에 COW가 구현되어 있으며, 타입에 직접 COW를 구현할 수도 있습니다.
간단한 코드를 통해 COW의 원리를 살펴보도록 하겠습니다.
var array1: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(UnsafeRawPointer(array1)) // 0x0000000100704210
var array2 = array1
print(UnsafeRawPointer(array2)) // 0x0000000100704210
array2.removeLast() // Copy-on-Write
print(UnsafeRawPointer(array1)) // 0x0000000100704210
print(UnsafeRawPointer(array2)) // 0x0000000100404e70
array1
을 선언하고 array2
에 array1
을 할당하면 두 인스턴스의 주소값이 동일한 것을 확인할 수 있습니다. COW에 의해 복사되지 않고 참조된 것입니다. 이때 array2
의 마지막 원소를 제거하는 메서드를 호출하면 수정이 발생하므로, 참조를 끊고 다른 메모리 공간을 할당합니다. 이후 array2
의 주소값을 확인하면 값이 변경된 것을 확인할 수 있습니다.
Reference and Value types in Swift - 야곰닷넷
Value and Reference Types - Swift Blog
위의 코드에서는 image를 받아오는 작업이 동기 메소드 Data(contentsOf: imageURL)이기 때문에 다운로드가 끝날 때까지 화면이 멈춰버리게 됨 🙅
출처: 부스트코스 5. 영화정보 애플리케이션 - 4. GCD - 3) DispatchQueue를 활용한 비동기 프로그래밍
→ 셀의 인덱스가 바껴버림 (= 다른 위치에 가있는 셀이 될 수 있다)
셀이 데이타를 세팅해주고 있는 인덱스와
다운로드가 끝났을 때의 인덱스가 상이할 수 있기 때문에
고거를 구분해주고
서로 일치하는 상황에서만
이미지를 세팅해줘야 한다!
그래서 같을 때만 셀에다가 이미지를 세팅해달라고 처리해둔 것임
if index.row == indexPath.row
셀의 imageView의 image는 없애줘야 함
그래야지 나중에 이미지 가져오기 전에 다른 사람 이미지가 표현이 안되있는 상태로 비워줘야 함
cell.imageView?.image = nil
DispatchQueue.global().async {
guard let imageURL: URL = URL(string: item.thumbnails.first!) else { return }
guard let imageData: Data = try? Data(contentsOf: imageURL) else { return }
DispatchQueue.main.async {
if let index: IndexPath = tableView.indexPath(for: cell) {
if index.row == indexPath.row {
cell.itemThumbnail.image = UIImage(data: imageData)
}
}
}
}
이전과 달리 이미지를 비동기로 받아오도록 바꿔줌
테이블뷰는 잘 받아오는데
똑같이 작성한 컬렉션뷰는 이미지를 못 받아오는 현상 발생... 😣
원인이 무엇일까? 🤔
아직 해결 몬함 😣
이미 스토리보드에서 추가해줬으므로 코드로 또 넣어줄 필요 없음