
class Counter {
var value = 0
private let lock = NSLock()
func increment() {
lock.lock()
value += 1
print("Value: \(value)")
lock.unlock()
}
func decrement() {
lock.lock()
value -= 1
print("Value: \(value)")
lock.unlock()
}
}
let counter = Counter()
let queue = DispatchQueue(label: "com.example.queue", attributes: .concurrent)
let group = DispatchGroup()
for _ in 0..<100 {
group.enter()
queue.async {
counter.increment()
group.leave()
}
group.enter()
queue.async {
counter.decrement()
group.leave()
}
}
group.notify(queue: .main) {
print(counter.value)
}
// 0
Counter라는 클래스를 정의하고, increment()와 decrement() 메서드를 사용하여 값을 증가시키거나 감소시킵니다. NSLock 클래스를 사용하여 Lock을 생성하고, lock() 메서드로 잠그고 unlock() 메서드로 잠금을 해제한다.increment()와 decrement() 메서드가 동시에 호출되더라도 값의 증감이 올바르게 동작한다. Product > Scheme > Edit Scheme을 선택한다.Run을 선택하고, 오른쪽의 Diagnostics 탭으로 이동한다.Thread Sanitizer 체크박스를 활성화하고 Close 버튼을 클릭한다.private let threadSafeCountQueue = DispatchQueue(label: "...")
private var _count = 0
public var count: Int {
get {
return threadSafeCountQueue.sync {
_count
}
}
set {
threadSafeCountQueue.sync {
_count = newValue
}
}
}
threadSafeCountQueue는 시리얼 큐이다.sync의 의미는 "글로벌 디폴트큐"에서 "시리얼 큐"로 보낸 작업을 기다린다는 의미private let threadSafeCountQueue = DispatchQueue(label: "...", attributes: .concurrent)
private var _count = 0
public var count: Int {
get {
return threadSafeCountQueue.sync {
return _count
}
}
set {
threadSafeCountQueue.async(flags: .barrier) { [unowned self] in
self._count = newValue
}
}
}
class SharedInstanceClass {
lazy var testVar = {
return Int.random(in: 0..<99)
}()
}
let queue = DispatchQueue(label: "test", qos: .default, attributes: [.initiallyInactive, .concurrent], autoreleaseFrequency: .workItem, target: nil)
let group = DispatchGroup()
let instance = SharedInstanceClass()
for i in 0 ..< 10 {
group.enter()
queue.async(group: group, qos: .default) {
let id = i
print("\(id) \(instance.testVar)")
group.leave()
}
}
queue.activate()
group.wait()
class SharedInstanceClass2 {
let serialQueue = DispatchQueue(label: "serial")
lazy var testVar = {
return Int.random(in: 0...100)
}()
// 객체 내부에서 시리얼큐로 다시 testVar에 접근하도록
var readVar: Int {
serialQueue.sync {
return testVar
}
}
}
// 디스패치그룹 생성
let group2 = DispatchGroup()
// 객체 생성
let instance2 = SharedInstanceClass2()
// 실제 비동기 작업 실행
for i in 0 ..< 100 {
group2.enter()
queue.async(group: group2) {
print("id:\(i), lazy var 이슈:\(instance2.readVar)")
group2.leave()
}
}
group2.notify(queue: DispatchQueue.global()){
print("시리얼큐로 해결한 모든 작업의 완료.")
}
queue.activate()
group1.wait()
class SharedInstanceClass4 {
lazy var testVar = {
return Int.random(in: 0...100)
}()
}
// 디스패치그룹 생성
let group4 = DispatchGroup()
// 객체 생성
let instance4 = SharedInstanceClass4()
let semaphore = DispatchSemaphore(value: 1)
// 실제 비동기 작업 실행
for i in 0 ..< 100 {
group4.enter()
semaphore.wait()
queue.async(group: group4) {
print("id:\(i), lazy var 이슈:\(instance4.testVar)")
group4.leave()
semaphore.signal()
}
}
group4.notify(queue: DispatchQueue.global()){
print("디스패치 세마포어로 해결한 모든 작업의 완료.")
}
class SharedInstanceClass3 {
lazy var testVar = {
return Int.random(in: 0...100)
}()
}
// 디스패치그룹 생성
let group3 = DispatchGroup()
// 객체 생성
let instance3 = SharedInstanceClass3()
// 실제 비동기 작업 실행
for i in 0 ..< 100 {
group3.enter()
queue.async(flags: .barrier) {
print("id:\(i), lazy var 이슈:\(instance3.testVar)")
group3.leave()
}
}
group3.notify(queue: DispatchQueue.global()){
print("디스패치 배리어로 해결한 모든 작업의 완료.")
}
제가 학습한 내용을 요약하여 정리한 것입니다. 내용에 오류가 있을 수 있으며, 어떠한 피드백도 감사히 받겠습니다.
감사합니다.