Question Of Concurrency and Threading

chaubeyAlok
11 min readFeb 11, 2021

Common Questions

  • What is Concurrency?
  • Difference between Concurrency and parallelism
  • What are the ways to achieve Concurrency in iOS?
  • What difference between GCD and NSOperations
  • What are NSThread
  • When to use NSOperation and When to use GCD
  • What is Lock
  • How to avoid race condition (Reader/ Writer problem)
  • How to make anything Thread Safe

Definition of

  • Thread
  • Operation
  • Queue (a type of Queue)
  • Process

Question on GCD

  • What does GCD stand for
  • What are the benefits of using GCD over NSoperations?
  • How to put dependencies in GCD
  • Can we cancel the task in GCD?
  • How to Put dependencies in a background thread with GCD
  • What is the Use of DispatchWorkItem?

Question on NSOperations

  • How to put dependencies on Operation
  • Write syntax to cancel the running task
  • What is the Advantage of Using NSOperations
  • Why apple have to introduce GCD when there was already Operation

Scenario Questions

  • Suppose you have given three different Apis to fetch data from the server and based on the collective response of all these APIs you have to render UI. how to hit API and how will you monitor if all the APIs have excuted.
  • If you have API running in a background thread and you want that API to wait for a while how would you do that?
  • Why Do we update UI in the main thread only (why can’t we do on the background thread)

Output-based Questions (You can copy paste these on playground)

let serialQueue = DispatchQueue.init(label: “serial”) // serial Queue created
let
anotherSerialThread = DispatchQueue.init(label: “serial1”) // another Serial Queue
let
concurrnetQueue = DispatchQueue.init(label: “concurrent”, attributes: .concurrent) // Concurrent Queue

//Guess the output of each block of code

1.DispatchQueue.main.sync {
// print(Thread.isMainThread) // Guess the output here
}

2. DispatchQueue.main.async. {
// print(Thread.isMainThread) //
//print(“inside the block”)
}
print(“before print”) // this print is part of the program

3. serialQueue.async {
// print(Thread.isMainThread) // its not a main thread
DispatchQueue.main.sync {
// print(Thread.isMainThread) // its main thread
// print(“will it compile”) // it just did
}
}

//print(“hello print”)
//print(“before print”)

4. serialQueue.async {
// print(Thread.isMainThread) // its not a main thread
serialQueue.sync {
// print(Thread.isMainThread) // its main thread
// print(“will it compile”) // it just did
}
}
//print(“hello print”)
//print(“before print”)

//serialQueue.sync {

// print(Thread.isMainThread) // its not a main thread

// serialQueue.async {

// print(Thread.isMainThread) // its main thread

// print(“will it compile”) // it just did

// }

//

//}

//print(“hello print”)

//serialQueue.sync { //***

// print(Thread.isMainThread) // its main Thread

// DispatchQueue.main.sync {

// print(“will it compile “) // it won’t compile (calling from main thread)

// print(Thread.isMainThread) // its main Thread

// }

//}

//concurrnetQueue.sync { //***

// print(“concurrnetQueue is on main thread \(Thread.isMainThread)”) // its main Thread

// DispatchQueue.main.sync {

// print(“will it compile “) // it won’t compile (calling from main thread)

// print(Thread.isMainThread) // its main Thread

// }

//}

//concurrnetQueue.sync { //***

// print(“concurrnetQueue is on main thread \(Thread.isMainThread)”) // its main Thread

// DispatchQueue.global(qos: .background).sync {

// print(“will it compile “) // it won compile (calling from main thread)

// print(Thread.isMainThread) // its main Thread

// }

//}

//print(“outside”)

//concurrnetQueue.async { //***

// print(“concurrnetQueue is on main thread \(Thread.isMainThread)”) // its main Thread

// DispatchQueue.main.sync {

// print(“will it compile “) // it won’t compile (calling from main thread)

// print(Thread.isMainThread) // its main Thread

// }

//}

//

//print(“before print”)

//concurrnetQueue.sync {

// print(Thread.isMainThread) // its not a main thread

// concurrnetQueue.sync {

// print(Thread.isMainThread) // its main thread

// print(“will it compile finally”) // it just did

// }

//

//}

//print(“hello print”)

//anotherSerialThread.sync { //***

// print(“first print”)

// serialQueue.sync { //***

// print(Thread.isMainThread) // its main Thread

// DispatchQueue.main.sync {

// print(“will it compile “) // it won’t compile (calling from main thread)

// print(Thread.isMainThread) // its main Thread

// }

// }

//}

//anotherSerialThread.sync { //***

// print(“first print”)

// serialQueue.async { //***

// print(Thread.isMainThread) // its main Thread

// DispatchQueue.main.sync {

// print(“will it compile “) // it won’t compile (calling from main thread)

// print(Thread.isMainThread) // its main Thread

// }

// }

//}

/*

############################ Dead lock On Serail Queue when There is sync inside sync

*/

//serialQueue.sync { ***

// print(Thread.isMainThread) // its main Thread

// print(“will it work”) // it did work

//}

// Global Queue with serial queue

/*

If Sync is called from main thread … despite of global quest it will be on main thread

QOS matters only on the concurrent thread

*/

func gloablQuessAsync() {

DispatchQueue.global(qos: .background).async {

print(“background”)

print(Thread.isMainThread)

}

DispatchQueue.global(qos: .userInitiated).async {

print(“userInitiated”)

print(Thread.isMainThread)

}

DispatchQueue.global(qos: .default).async {

print(“default”)

print(Thread.isMainThread)

}

DispatchQueue.global(qos: .userInteractive).async {

print(“userInteractive”)

print(Thread.isMainThread)

}

DispatchQueue.global(qos: .utility).async {

print(“utility”)

print(Thread.isMainThread)

}

DispatchQueue.global(qos: .unspecified).async {

print(“unspecified”)

print(Thread.isMainThread)

}

}

func gloablQuess() {

DispatchQueue.global(qos: .background).sync {

print(“background”)

print(Thread.isMainThread)

}

DispatchQueue.global(qos: .userInitiated).sync {

print(“userInitiated”)

print(Thread.isMainThread)

}

DispatchQueue.global(qos: .default).sync {

print(“default”)

print(Thread.isMainThread)

}

DispatchQueue.global(qos: .userInteractive).sync {

print(“userInteractive”)

print(Thread.isMainThread)

}

DispatchQueue.global(qos: .utility).sync {

print(“utility”)

print(Thread.isMainThread)

}

DispatchQueue.global(qos: .unspecified).sync {

print(“unspecified”)

print(Thread.isMainThread)

}

}

//serialQueue.sync {

// gloablQuessAsync()

//}

//serialQueue.async {

// gloablQuess()

//}

/*

Nested Sync on the same thread will bring the deadlock

*/

//serialQueue.sync {

// print(“a”)

// anotherSerialThread.sync {

// print(“hello”)

// }

// concurrnetQueue.async { // DispatchQueue.main this is serial queue

// print(“b”)

// concurrnetQueue.sync {

// for inx in 0…50 {

// print(inx)

// }

// }

// serialQueue.async {

// print(“c”)

// }

// }

// print(“outside”)

//}

//

//serialQueue.async {

// print(“a”)

// serialQueue.async {

// print(“bb”)

//// serialQueue.sync {

//// print(“cc”)

//// }

// }

// print(“b1”)

// for inx in 0…100 {

// print(inx)

// }

//}

//print(“a1”)

//serialQueue.async {

// print(“a”)

// serialQueue.sync {

// print(“bb”)

// serialQueue.sync {

// print(“cc”)

// }

// }

//}

//print(“a1”)

//serialQueue.sync {

// print(“a”)

// serialQueue.sync {

// print(“bb”)

// serialQueue.async {

// print(“cc”)

// }

// }

//}

//print(“a1”)

//serialQueue.sync {

// print(“a”)

// serialQueue.async {

// print(“bb”)

// serialQueue.async {

// print(“cc”)

// }

// print(“dd”)

// }

// print(“ee”)

//}

//print(“outside”)

//

//serialQueue.sync {

// print(“a”)

// serialQueue.async {

// print(“bb”)

// serialQueue.async {

// print(“cc”)

// serialQueue.async {

// print(“cc1”)

// serialQueue.async {

// print(“cc2”)

// serialQueue.sync {

// print(“cc3”)

// }

// }

// }

// }

// print(“dd”)

// }

// print(“ee”)

//}

//print(“outSide”)

//############### Concurrent Queues

//concurrnetQueue.sync {

// print(“a”)

// print(“b”)

// print(“c”)

// print(“d”)

// for i in 0..<100 {

// print(i)

// }

// for i in 1..❤00 {

// print(i)

// }

//

// print(“e”)

// print(“f”)

//}

//print(“outside”)

//

//

//concurrnetQueue.async {

// print(“a”)

// print(“b”)

// print(“c”)

// print(“d”)

// for i in 0..<100 {

// print(i)

// }

// for i in 1..❤00 {

// print(i)

// }

//

// print(“e”)

// print(“f”)

//}

//print(“outside1”)

//

//concurrnetQueue.sync {

// concurrnetQueue.async {

// for i in 1..❤000 {

// }

// print(“a”)

// }

// concurrnetQueue.async {

// for i in 1..❤000000 {

// }

// print(“b”)

// }

// concurrnetQueue.async {

// for i in 1..❤000000 {

// }

// print(“C”)

//

// }

//

// concurrnetQueue.async {

// for i in 1..❤0000 {

// }

// print(“d”)

//

// }

//

// concurrnetQueue.async {

// for i in 1..❤00000 {

// }

// print(“e”)

//

// }

// concurrnetQueue.async {

// for i in 1..❤0099 {

// }

// print(“f”)

//

// }

//

// concurrnetQueue.async {

// for i in 1..❤0210 {

// }

// print(“g”)

//

// }

// for i in 1..❤00 {

// }

// print(“Inside”)

//}

//print(“outSide”)

//concurrnetQueue.async {

//// print

// concurrnetQueue.sync {

// for i in 1..❤00000 {

//

// }

// print(“a”)

// }

// concurrnetQueue.sync {

// print(“b”)

// for i in 1..❤00000 {

// }

// }

// concurrnetQueue.async {

// for i in 1..❤00000 {

// }

// print(“c”)

// }

// concurrnetQueue.sync {

// for i in 1..❤00000 {

// }

// print(“f”)

// for i in 1..❤00000 {

// }

// }

//}

//

//print(“outSide”)

//########################## Mixed caseres

//concurrnetQueue.sync {

// serialQueue.sync {

// for i in 0..❤0000 {

//

// }

// print(“a”)

// }

// serialQueue.async {

// for i in 0..❤0 {

//

// }

// print(“b”)

// }

//}

//print(“outSide”)

//concurrnetQueue.sync { // importat

// serialQueue.sync {

// for i in 0..❤0000 {

//

// }

// print(“a”)

// }

// serialQueue.async {

// print(“b”)

// }

//}

//print(“outSide”)

//concurrnetQueue.sync { // importat

// serialQueue.async {

// for i in 0..❤0000 {

//

// }

// print(“a”)

// }

// serialQueue.async {

// print(“b”)

// }

//}

//print(“outSide”)

//concurrnetQueue.async { // importat

// serialQueue.sync {

// for i in 0..❤0000 {

//

// }

// print(“a”)

// }

// serialQueue.async { // sync async doesnt matter on serail queur

// print(“b”)

// }

//}

//print(“outSide”)

//concurrnetQueue.async { // importat

// serialQueue.async {

// for i in 0..❤00000000 {

//

// }

// print(“a”)

// }

// serialQueue.async { // sync async doesnt matter on serail queur

// print(“b”)

// }

//}

//print(“outSide”)

//concurrnetQueue.async { // importat

// serialQueue.async {

// for i in 0..❤00 {

//

// }

// print(“a”)

// }

// anotherSerialThread.async {

// print(“b”)

// }

//}

//print(“outSide”)

//serialQueue.async { // importat

// serialQueue.async {

// for i in 0..❤000 {

//

// }

// print(“a”)

// }

// serialQueue.async { // sync async doesnt matter on serail queur

// print(“b”)

// }

//}

//print(“outSide”)

//***

//concurrnetQueue.async { // importat

// concurrnetQueue.sync {

// for i in 0..❤0000000000 {

//

// }

// print(“a”) //

// }

// concurrnetQueue.async {

// print(“b”)

// }

//}

//print(“outSide”)

//concurrnetQueue.async { // importat

// concurrnetQueue.async {

// for i in 0..❤0000000000 {

//

// }

// print(“a”) //

// }

// concurrnetQueue.async {

// print(“b”)

// }

//}

//print(“outSide”)

// Data inSide Queue goes as FIFO .. so if the first data is of sync type then it will make other thigs to wait

//Conculustion

//concurrnetQueue.sync {

// //item in Queue as FIFO

// //block will retain the access as long as all of the data gets excuted

//}

//

//

//concurrnetQueue.async {

// //item in Queue as FIFO

// //Code will come out of the scope as soon as all item are interserted in queue

//}

//

//serialQueue.sync {

// //item in Queue as FIFO

// //block will retain the access as long as all of the data gets excuted

//}

//

//serialQueue.async {

// //item in Queue as FIFO

// //Code will come out of the scope as soon as all item are interserted in queue

//}

//Note:-

//serialQueue.async { serialQueue.async {

//

// } }

//order of excution remains same

//eg.

//serialQueue.async {

// anotherSerialThread.async {

// for i in 0..❤0000 {

// }

// print(“a”)

// }

// anotherSerialThread.async {

// for i in 0..❤0000 {

// }

// print(“b”)

// }

//

// anotherSerialThread.async {

// for i in 0..❤0000 {

// }

// print(“c”)

// }

//

// anotherSerialThread.async {

// for i in 0..❤0000 {

// }

// print(“d”)

// }

//

// anotherSerialThread.async {

// for i in 0..❤0000 {

// }

// print(“e”)

// }

//

//}

// with async we get immeditae call back from the block … does wait if items have insertedf in the queus or not

//concurrnetQueue.async { // importtat concent

// anotherSerialThread.sync {

// print(“start of 1”)

// for i in 0..❤0000000 {

// }

// print(“a”)

// }

// anotherSerialThread.sync {

// print(“start of 2”)

//

// for i in 0..❤0000000 {

// }

// print(“b”)

// }

//

// anotherSerialThread.sync {

// print(“start of 3”)

//

// for i in 0..❤0000000 {

// }

// print(“c”)

// }

//

// anotherSerialThread.sync {

// print(“start of 4”)

//

// for i in 0..❤0000000 {

// }

// print(“d”)

// }

//

// anotherSerialThread.sync {

// print(“start of 5”)

//

// for i in 0..❤0000000 {

// }

// print(“e”)

// }

// print(“inSide”)

//

//}

//print(“outSside”)

//serialQueue.async {

// anotherSerialThread.sync {

// print(“start of 1”)

// for i in 0..❤0000000 {

// }

// print(“a”)

// }

// anotherSerialThread.sync {

// print(“start of 2”)

//

// for i in 0..❤0000000 {

// }

// print(“b”)

// }

//

// anotherSerialThread.sync {

// print(“start of 3”)

//

// for i in 0..❤0000000 {

// }

// print(“c”)

// }

//

// anotherSerialThread.sync {

// print(“start of 4”)

//

// for i in 0..❤0000000 {

// }

// print(“d”)

// }

//

// anotherSerialThread.sync {

// print(“start of 5”)

//

// for i in 0..❤0000000 {

// }

// print(“e”)

// }

// print(“inSide”)

//

//}

//print(“outSside”)

//serialQueue.async {

// print(“Alok”)

// print(Thread.isMainThread)

//

// DispatchQueue.main.sync {

// print(Thread.isMainThread)

//

// print(“chaubey”)

// }

// DispatchQueue.main.async {

// print(Thread.isMainThread)

//

// print(“Hey”)

// }

//}

//

//

//serialQueue.sync {

// print(“Alok”)

// print(Thread.isMainThread)

//

// DispatchQueue.main.async {

// print(Thread.isMainThread)

//

// print(“chaubey”)

// }

// DispatchQueue.main.async {

// print(Thread.isMainThread)

//

// print(“Hey”)

// }

//}

//

//

//

//serialQueue.async {

// print(“Alok”)

// print(Thread.isMainThread)

//

// DispatchQueue.main.sync {

// print(Thread.isMainThread)

//

// print(“chaubey”)

// }

// DispatchQueue.main.sync {

// print(Thread.isMainThread)

//

// print(“Hey”)

// }

//}

//serialQueue.sync {

// print(“Alok”)

// print(Thread.isMainThread)

//

// DispatchQueue.main.sync {

// print(Thread.isMainThread)

//

// print(“chaubey”)

// }

// DispatchQueue.main.sync {

// print(Thread.isMainThread)

//

// print(“Hey”)

// }

//}

//concurrnetQueue.sync {

// print(“chaubey”)

// print(Thread.isMainThread)

//

// DispatchQueue.main.sync {

// print(Thread.isMainThread)

//

// print(“chaubey Ji”)

// }

////

// DispatchQueue.main.async {

// print(Thread.isMainThread)

//

// print(“chaubey jiIe”)

//

// }

//

//}

//Race Condtion

//let myLock = NSLock()

//myLock.lock()

//myLock.unlock()

//

//Flag barrier

//concurrnetQueue.async( flags: .barrier) { // happends only concurrent thread

// //Not the thread will run like a serail queue

//}

//let semaphore = DispatchSemaphore.init(value: 1) //values says how many threadsa will will be available for the excution

//semaphore.wait() //waiting for excution

//semaphore.signal() // release of the resouces

// Incase of multile Queues the one with the first on Queue for excution will be excuted

//var array = [Int] ()

//DispatchQueue.concurrentPerform(iterations: 100) { index in

// let last = array.last ?? 0

// array.append(last + 1)

//}

//print(array)

//Solved usning lock

//let myLock = NSLock()

//

//var array = [Int] ()

//

//DispatchQueue.concurrentPerform(iterations: 100) { index in

// myLock.lock()

// let last = array.last ?? 0

// array.append(last + 1)

// myLock.unlock()

//}

//print(array)

//var array = [Int] ()

//serialQueue.async {

// DispatchQueue.concurrentPerform(iterations: 100) { index in

// let last = array.last ?? 0

// array.append(last + 1)

// }

//}

//

//print(array)

//var array = [Int] ()

//serialQueue.async {

// DispatchQueue.concurrentPerform(iterations: 100) { index in

// let last = array.last ?? 0

// array.append(last + 1)

// }

// print(array)

//

//}

//var array = [Int] ()

// DispatchQueue.concurrentPerform(iterations: 100) { index in

// serialQueue.async {

// let last = array.last ?? 0

// array.append(last + 1)

// }

// print(array)

//

//}

//var array = [Int] ()

// DispatchQueue.concurrentPerform(iterations: 100) { index in

// serialQueue.sync {

// let last = array.last ?? 0

// array.append(last + 1)

// }

//}

//print(array)

//var array = [Int] ()

// DispatchQueue.concurrentPerform(iterations: 100) { index in

// serialQueue.sync {

// let last = array.last ?? 0

// array.append(last + 1)

// }

// print(array)

//}

//var array = [Int] ()

// DispatchQueue.concurrentPerform(iterations: 100) { index in

// serialQueue.async( flags: .barrier) {

// let last = array.last ?? 0

// array.append(last + 1)

// print(array)

//

// }

//}

//var array = [Int] ()

// DispatchQueue.concurrentPerform(iterations: 100) { index in

// concurrnetQueue.async( flags: .barrier) {

// let last = array.last ?? 0

// array.append(last + 1)

// print(array)

//

// }

// print(array)

//

//}

//var array = [Int] ()

//concurrnetQueue.async( flags: .barrier) {

// DispatchQueue.concurrentPerform(iterations: 100) { index in

// let last = array.last ?? 0

// array.append(last + 1)

// }

// print(array)

//}

//

//concurrnetQueue.async( flags: .barrier) {

//

// print(“a”)

// print(“b”)

// print(“c”)

// print(“d”)

// print(“e”)

// print(“f”)

// print(“g”)

// print(“h”)

// print(“i”)

// print(“j”)

// print(“k”)

// print(“a1111”)

// print(“b1111”)

// print(“c1111”)

// print(“d1111”)

// print(“e1111”)

// print(“f1111”)

// print(“g1111”)

// print(“h1111”)

// print(“i1111”)

// print(“j1111”)

// print(“k1111”)

//

//}

//var array = [Int] ()

//serialQueue.async {

// DispatchQueue.concurrentPerform(iterations: 100) { index in

// let last = array.last ?? 0

// array.append(last + 1)

// }

// print(array)

//

//}

//What is dispath work item

--

--