[COMPLETE] - Deep Dive Multithreading Practice

Overview

Multithreading-Deep-Dive

[IN-PROGRESS]

Deep Dive(C-level) Multithreading Practice

  • Threads
  • Operations
  • Grand Central Dispatch (GCD)

Concurrency Problems:

Race Conditions – Occurs when processes that must occur in a particular order occur out of order due to multiple threading.

Deadlock – Occurs when two competing processes are waiting for each other to finish, allowing neither to finish.

Starvation – Occurs when a process never gains accesses to resources, never allowing the program to finish.

Livelock – Occurs when two threads are dependent on each other signals and are both threads respond to each others signals. If this is the case, the threads can cause a loop similar to something between a deadlock and starvation.

Priority inversion - Technically speaking, priority inversion occurs when a queue with a lower quality of service is given higher system priority than a queue with a higher quality of service, or QoS.


Steps to Queue Management:

1) Global vs Main(serial queue)

2) Set priority for Global

The QoS classes are:

User-interactive: This represents tasks that must complete immediately in order to provide a nice user experience. Use it for UI updates, event handling and small workloads that require low latency. The total amount of work done in this class during the execution of your app should be small. This should run on the main thread.

User-initiated: The user initiates these asynchronous tasks from the UI. Use them when the user is waiting for immediate results and for tasks required to continue user interaction. They execute in the high priority global queue.

Utility: This represents long-running tasks, typically with a user-visible progress indicator. Use it for computations, I/O, networking, continuous data feeds and similar tasks. This class is designed to be energy efficient. This will get mapped into the low priority global queue.

Background: This represents tasks that the user is not directly aware of. Use it for prefetching, maintenance, and other tasks that don’t require user interaction and aren’t time-sensitive. This will get mapped into the background priority global queue.

3) Sync vs Async




Mutex

Mutex — ensures that only one thread is active in a given region of code at a time. You can think of it as a semaphore with a maximum count of 1.

Mutex is blocking and releasing objects

when the object is Mutex protected - the thread pinging it is in WAIT mode until Mutex is released

SWIFT can't do anything about threads. It uses either Libraries(GCD) or Objective-C(nsThread) C-level functions work 15-20 faster than GCD or NSLock!!!

Mutex Code Example
// C-level
 
class SaveThread{
    private var mutex = pthread_mutex_t()
    
    init(){
        pthread_mutex_init(&mutex, nil)
    }
    
    func someMethod(completion: ()->Void){
        //locking our object
        pthread_mutex_lock(&mutex)
        
        // some data blah-blah
        // call completion to pass the completion parameter
        completion()
        
        
        // in case there is a crash, our thread won't be unlocked. That is why we need to use DEFER. It will guaranteed to unlock thread
        
        defer{
            //unlocking object
            pthread_mutex_unlock(&mutex)
        }
    }
}


// Objective-C level

class SaveThread{
    private let lockMutex = NSLock()
    
    func someMethod(completion: ()->Void){
        
        lockMutex.lock()
        completion()
        
        
        defer{
            lockMutex.unlock()
        }
    }
}





WorkItem

DispatchWorkItem - abstraction level to wrap your task so you can start/cancel/notify/etc your task.

NOTE! GCD cannot cancel workItem if already started. YET Operations can, so many switch to operations


Semaphore

A semaphore consists of a threads queue and a counter value (type Int). The threads queue is used by the semaphore to keep track of waiting threads in FIFO order (The first thread entered into the queue will be the first to get access to the shared resource once it is available).

Semaphore with value == 1 (number of active threads), is MUTEX. So just one thread allowed.

Semaphore Code Example
let semaphore = DispatchSemaphore(value: 0)

queue.async {
    semaphore.wait() // value-=1 , leaving one thread available
    sleep(3)
    print(Thread.current)
    print("Method 1")
    semaphore.signal() // value+=1, adding one more thread
}


DispatchGroup

Groups allow you to aggregate a set of tasks and synchronize behaviors on the group. You attach multiple work items to a group and schedule them for asynchronous execution on the same queue or different queues. When all work items finish executing, the group executes its completion handler. You can also wait synchronously for all tasks in the group to finish executing.

DispatchGroup Code Example (Serial Queue)
class DispatchGroupTest1{
    
    private let queueSerial = DispatchQueue(label: "DispatchGroupQueue1")
    private let groupRed = DispatchGroup()
    
    func loadInfo(){
        queueSerial.async(group: groupRed){
            sleep(1)
            print("1")
        }
        
        queueSerial.async(group: groupRed){
            sleep(1)
            print("2")
        }
        // Similar to WorkItem
        groupRed.notify(queue: .main) {
            print("Finished All")
        }
    }
}


DispatchBarrier

The .barrier flag means that it will wait until every currently running block in the queue is finished executing before it executes. Other blocks will queue up behind it and be executed when the barrier dispatch is done.

When the barrier is executing, it essentially acts as a serial queue. That is, the barrier is the only thing executing. After the barrier finishes, the queue goes back to being a normal concurrent queue.

DispatchBarrier Code Example
private let concurrentQueue = DispatchQueue(label: "com.gcd.dispatchBarrier", attributes: .concurrent)
for value in 1...5 {
    concurrentQueue.async() {
        print("async \(value)")
    }
}
for value in 6...10 {
    concurrentQueue.async(flags: .barrier) {
        print("barrier \(value)")
    }
}
for value in 11...15 {
    concurrentQueue.async() {
        print("sync \(value)")
    }
}


PRINTOUT:
// NOTE: The race condition for the first 5 items:
async 1
async 5
async 2
async 3
async 4
barrier 6
barrier 7
barrier 8
barrier 9
barrier 10
sync 11
sync 12
sync 13
sync 14
sync 15



DispatchSource

An object that coordinates the processing of specific low-level system events, such as file-system events, timers, and UNIX signals. Like timers, observe changes in a file on the file system, socket management etc


Operation & OperationQueue & OperationBlock

One of key difference GCD and Operation, that in Operation the task can be canceled even when it is started execution. In GCD once queue started - no way to cancel a task.

Operations Code Example
print(Thread.current) //main

class OperationA: Operation{
    
    override func main() {
        print("inside",Thread.current)
        print("Test Operation") // global when with Operation
    }
}

let operationA = OperationA()
//operationA.start()

let queue1 = OperationQueue()
queue1.addOperation(operationA)

BlockOperation & WaitUntilFinished & OperationCancel

WaitUntil Code Example
class WaitOperationTest{
    
    private let operationQueue = OperationQueue()
    
    func check(){
        operationQueue.addOperation {
            sleep(1)
            print("Test 1")
        }
        
        operationQueue.addOperation {
            sleep(2)
            print("Test 2")
        }
        
        // Barrier that blocks below until above is finisged
        operationQueue.waitUntilAllOperationsAreFinished()
        operationQueue.addOperation {
            print("Test 3")
        }
        
        operationQueue.addOperation {
            print("Test 4")
        }
    }
}

let waitOperationTest = WaitOperationTest()
waitOperationTest.check()

PRINT OUT:
Test 1
Test 2
Test 3
Test 4

CompletionBlock Code Example
class CompletionBlockTest{
    private let operationQueue = OperationQueue()

    
    func check3(){
        let operation1 = BlockOperation{
            sleep(1)
            print("Test 1 ")
        }
        // Completion Block
        operation1.completionBlock = {
            print("Completion Block Finished")
        }
        operationQueue.addOperation(operation1)
    }
}

let completionBlockTest = CompletionBlockTest()
completionBlockTest.check3()

You might also like...
Digger is a lightweight download framework that requires only one line of code to complete the file download task
Digger is a lightweight download framework that requires only one line of code to complete the file download task

中文说明 Digger is a lightweight download framework that requires only one line of code to complete the file download task. Based on URLSession, pure Swif

Challenging each other to complete pet projects!

Podlodka Pet Project Challenge Мотивируем друг друга на завершение своих пет проджектов! Каждую неделю каждый участник вносит в банк 1 ставку и ведет

Learn to Code While Building Apps - The Complete iOS Development Bootcamp
Learn to Code While Building Apps - The Complete iOS Development Bootcamp

Xylophone Our Goal The goal of this tutorial is to dive into a simple iOS recipe - how to play sound and use an Apple library called AVFoundation. The

Starter code for the Flash Chat project in the Complete iOS Development Bootcamp
Starter code for the Flash Chat project in the Complete iOS Development Bootcamp

Flash-Chat Our Goal One of the most fundamental component of modern iOS apps is the Table View. Table Views are used everywhere from the Mail app to t

A Fast and Complete Swift Drawing Library

FastDraw A Fast and Complete Swift Drawing Library Description FastDraw is a high performance and highly extensible Drawing Library that supports Appl

Complete SwiftUI Docs with Examples

🍻 SwiftOnTap Complete SwiftUI Docs with Examples. Get Started | How It Works | Add Docs Get Started To get started, Go to swiftontap.com 👉 . Press /

A complete Mac App: drag an image file to the top section and the bottom section will show you the text of any QRCodes in the image.

QRDecode A complete Mac App: drag an image file to the top section and the bottom section will show you the text of any QRCodes in the image. QRDecode

Learn to Code While Building Apps - The Complete iOS Development Bootcamp
Learn to Code While Building Apps - The Complete iOS Development Bootcamp

BMI Calculator Our Goal The goal of this tutorial is to learn more about Optionals, solidify your understanding of the MVC design pattern and to intro

Complete Animated GIF Support for iOS, with Functions, NSJSONSerialization-style Class, and (Optional) UIImage Swizzling
Complete Animated GIF Support for iOS, with Functions, NSJSONSerialization-style Class, and (Optional) UIImage Swizzling

AnimatedGIFImageSerialization This library is no longer maintained. In iOS 13+ and macOS 10.15+, use CGAnimateImageAtURLWithBlock instead. AnimatedGIF

Project 03 I created for
Project 03 I created for "iOS & Swift - The Complete iOS App Development Bootcamp"

Dicee This is the third project I created for "iOS & Swift - The Complete iOS App Development Bootcamp" Our Goal The objective of this tutorial is to

Project 04 I created for
Project 04 I created for "iOS & Swift - The Complete iOS App Development Bootcamp"

Magic 8 Ball This is the fourth project I created for "iOS & Swift - The Complete iOS App Development Bootcamp" Our Goal The objective of this challen

CombineDriver - Drivers are Publishers which don't complete

CombineDriver Drivers are Publishers which don't complete. CombineDriver is a sm

 The App Brewery Complete App Development course project
The App Brewery Complete App Development course project

Destini The App Brewery Complete App Development course project. "A Choose Your

Tipsy - Bill splitting and tip calculating App developed during iOS & Swift classes - The Complete App Development Bootcamp
Tipsy - Bill splitting and tip calculating App developed during iOS & Swift classes - The Complete App Development Bootcamp

Tipsy 💵 Bill splitting and tip calculating App developed during iOS & Swift cla

rTracker is a complete iOS application for creating local on-device databases ('trackers') to log data with timestamps.
rTracker is a complete iOS application for creating local on-device databases ('trackers') to log data with timestamps.

rTracker is a complete iOS application for creating local on-device databases ('trackers') to log data with timestamps. Trackers can use a va

A complete ground-up rewrite of NoMAD utilizing the same AD Auth Framework found in NoMAD Login.

NoMAD 2 A complete ground-up rewrite of NoMAD utilizing the same AD Auth Framework found in NoMAD Login. Why? Well... that's a good question. NoMAD 1.

On-device wake word detection powered by deep learning.
On-device wake word detection powered by deep learning.

Porcupine Made in Vancouver, Canada by Picovoice Porcupine is a highly-accurate and lightweight wake word engine. It enables building always-listening

An open source library for building deep-linkable SwiftUI applications with composition, testing and ergonomics in mind
An open source library for building deep-linkable SwiftUI applications with composition, testing and ergonomics in mind

Composable Navigator An open source library for building deep-linkable SwiftUI applications with composition, testing and ergonomics in mind Vanilla S

Turning on a VPN is always a painful experience on an iOS device due to the deep nested menus.
Turning on a VPN is always a painful experience on an iOS device due to the deep nested menus.

VPN On Turning on a VPN is always a painful experience on an iOS device due to the deep nested menus. This App installs a Today Widget into Notificati

Owner
Anton Veldanov
Anton Veldanov
Project 03 I created for "iOS & Swift - The Complete iOS App Development Bootcamp"

Dicee This is the third project I created for "iOS & Swift - The Complete iOS App Development Bootcamp" Our Goal The objective of this tutorial is to

Lukas Goodfellow 0 Dec 23, 2021
RMSUI - A Simple Swift MVVM architectured Rick & Morty UI app in order to practice SwiftUI & GraphQL

RMSUI A Simple Swift MVVM architectured "Rick & Morty UI" app ?? in order to pra

null 0 Jan 24, 2022
A project to practice the Platzi course, Curso de Desarrollo de Aplicaciones iOS con SwiftUI

A project to practice the Platzi course, Curso de Desarrollo de Aplicaciones iOS con SwiftUI

Joaquin Segovia 1 Mar 14, 2022
SwiggyClone - A Swiggy clone will dive deep into UICompositional Layouts and alot of new concepts

SwiggyClone This app is a clone of Swiggy (in progress). In this project we will

Dheeraj Kumar Sharma 81 Dec 25, 2022
A camera app we will dive deep into AVFoundation library

Camera App In this project you are going to discover few concepts in Swift that I've been working on for few weeks, Core Animations with CAShape Layer

Dheeraj Kumar Sharma 12 Nov 13, 2022
GroceryMartApp-iOS-practice - To Practice fundamental SwiftUI feature like navigation, state mamagement, customazing etc

?? GroceryMartApp-iOS-practice 아래의 내용은 스윗한 SwiftUI 책의 실전 앱 구현하기 을 바탕으로 정리한 내용입니다

Jacob Ko 0 Jan 7, 2022
FruitsDic-ios-practice - To Practice onboarding , List, detail and setting View

?? FruitsDic-ios-practice ?? 기능 상세 OnBoding Screen with Page Tab View Data model

Jacob Ko 0 Jan 12, 2022
JSON-Practice - JSON Practice With Swift

JSON Practice Vista creada con: Programmatic + AutoLayout Breve explicación de l

Vanesa Giselle Korbenfeld 0 Oct 29, 2021
Controls-Practice-UIKit- - Controls Practice (UIKit)

Controls Practice (UIKit) Change a number 0 to 255 different ways: Button (+1) I

null 1 Feb 13, 2022
A complete set of primitives for concurrency and reactive programming on Swift

A complete set of primitives for concurrency and reactive programming on Swift 1.4.0 is the latest and greatest, but only for Swift 4.2 and 5.0 use 1.

AsyncNinja 156 Aug 31, 2022