Confusing with technical terminology between Thread and Queue - ios

I am newer to iPhone development. With focusing on develop multi-threading Apps, I have referred to some Apple documents and others explaining thread and multi-threading concepts. But as far as work-queue is concerned, I am confused in understanding relation between Thread, Task and Queue. Some documents says, a thread can have multiple tasks and those tasks is stored in queue, thus each thread may have its own queue. Whereas, some says that, threads themselves are stored in queue.
My question is, can we say:
(1) Threads can have multiple Tasks and those task are stored and managed inside a Queue of that thread.
OR
(2) Threads themselves are stored and managed inside a Queue.
Secondly, I also read something like this:
Another advantage of using a thread pool over creating a new thread for each task is thread creation and destruction overhead is negated.
Is thread pool synonym for work-queue?

I am clear now.
Thread and queue is totally different things. Thread is separate code of execution while queue is data structure for maintaining tasks. A thread can have multiple tasks and all threads may be created for particular goal that is Process. A thread has its own space in memory for its variables and other things.
So, in multi-threading programming, queue is a mechanism that handle sequence of tasks to be executed. Queue always executes tasks in serial order. However, if we want to execute tasks concurrently, we would have to create concurrent queues. Thus multiple queues can executed concurrently benefiting multiprogramming. With latest API, it is upto operating system that how to schedule those tasks. Tasks may or may not be executed on separate thread. Structure always depends on our requirement.

Related

Are threads shared between different Dispatch queues?

Can a single thread be used in different dispatch queues?
I'm developing an app where i want to get a value depending on the thread where the code is running. For that i change the name of the thread when the block starts in a custom queue.
For example, if I add a block to mi custom queue, and i change the name of that thread to "SyncThread". Does a block called in a default system queue will be executed in that "SyncThread"?
Can a single thread be used in different dispatch queues?
Yes, and this is common. (The concept of "different dispatch queues" is itself problematic, since queues can, and do, target other queues. Seemingly simple questions like "what is the current queue" are not well defined.)
I'm developing an app where i want to get a value depending on the thread where the code is running. For that i change the name of the thread when the block starts in a custom queue.
What you likely want for this is queue contextual data rather than thread-specific data (usually called thread-local storage). See DispatchQueue.setSpecific(key:value:).
You use the terms thread and queue interchangeably but they aren't interchangeable; they're two distinct things. Apple doesn't want developers threading anymore, they want developers queueing their tasks. The queueing is handled by GCD which does all the threading behind the scenes. This means that two queues can certainly run on the same thread. And while all tasks within a queue run on distinct threads, not every task is guaranteed to run on the same thread, so keep that in mind. Therefore, I would take the advice given here to focus instead on queue context, not thread context.

Threads and Queues in iOS - not NSThread

I'd like to get a conceptual understanding of serial/concurrent queues and threads in iOS. I have a solid grasp of the queue data structure and how it's used.
Are threads just, in an unofficial sense, an abstraction of a queue? Meaning they're implemented using queue data structures. Each queue is then an actual thread, but they act as queues in that processes are executed in a first in, first out fashion?
That would stand for serial queues, as those DO indeed follow FIFO, but then concurrent queues are a different ball game. You don't know what processes are executing when, and even though you have them on one queue, they are actually getting fired on different threads wherever there is availability? Meaning that queues can actually contain or refer to multiple threads?
Any help or pointers to resources (not including apple documentation, which I'm currently going through) would be greatly appreciated.
Queues are one of the methods to create threads in iOS.
A thread is the current execution of a code.
The main thread (Thread 0) is actually the single thread which runs always during the app lifetime. The others, if they are not attached to a NSRunLoop which have something like while(1) { code...}, then they'll finish immediately after the code is executed.
Wikipedia should be your friend: https://en.wikipedia.org/wiki/Thread_(computing)

GCD and Threads

I want to understand something about GCD and Threads.
I have a for loop in my view controller which asks my model to do some async network request.
So if the loop runs 5 times, the model sends out 5 network requests.
Is it correct to state that 5 threads have been created by my model considering the fact that I'm using NSURLConnection's sendAsyncRequest and the completion handlers will be called on an additional 5 threads ?
Now, If I ask my view controller to execute this for loop on a different thread and in every iteration of the loop, the call to the model should be dependent on the previous iteration, would I be creating an "Inception" of threads here ?
Basically, I want the subsequent async requests to my server only if the previous thread has completed entirely (By entirely I mean all of its sub threads should have finished executing too.)
I can't even frame the question properly because I'm massively confused myself.
But if anybody could help with anything, that would be helpful.
It is not correct to state that five threads have been created in the general case.
There is no one-to-one mapping between threads and blocks. GCD is an implementation of thread pooling.
A certain number of threads are created according to the optimal setup for that device — the cost of creating and maintaing threads under that release of the OS, the number of processor cores available, the number of threads it already has but which are presently blocked and any other factors Apple cares to factor in may all be relevant.
GCD will then spread your blocks over those threads. Or it may create new threads. But it won't necessarily.
Beyond that queues are just ways of establishing the sequencing between blocks. A serial dispatch queue does not necessarily own its own thread. All concurrent dispatch queues do not necessarily own their own threads. But there's no reason to believe that any set of queues shares any threads.
The exact means of picking threads for blocks has changed between versions of the OS. E.g. iOS 4 was highly profligate in thread creation, in a way that iOS 5+ definitely haven't been.
GCD will just try to do whatever is best in the circumstances. Don't waste your time trying to second guess it.
"Basically, I want the subsequent async requests to my server only if the previous thread has completed entirely (By entirely I mean all of its sub threads should have finished executing too.)"
Only focusing on the above statement to avoid confusion. Simple solution would be create a queue. feed the queue with 5 loops. Each loop will be making network request synchronously(you can use sendSynchronousRequest: method available in NSURLConnection), performing the operations after request completion and then start the next loop. queue following FIFO will execute the your requests subsequently.
GCD : Think of this as a simple queue that can accept tasks. Tasks are blocks of your code. You can put in as many tasks as you want in a queue (permitting system limits). Queues come in different flavors. Concurrent vs Serial. Main vs Global. High Priority vs Low Priority. A queue is not a thread.
Thread : It is a single line of execution of code in sequence. You can have multiple threads working on your code at the same time. A thread is not a queue.
Once you separate the 2 entities things start become clear.
GCD basically uses the threads in the process to work on tasks. In a serial queue everything is processed in sequence. So you don't need to have synchronization mechanisms in your code, the very nature of serial queue ensures synchronization. If this is a concurrent queue (i.e. 2 or more tasks being processed at the same time, then you need to ensure critical sections of your code are protected with synchronization).
Here is how you queue work to be done.
dispatch_async(_yourDispatchQueue, ^() {
NSLog (#"work queued");
});
The above NSLog will now get executed in a background thread in a near future time, but in a background thread.
If you notice when we put a request in we use dispatch_async. The other variation is dispatch_sync. The different between the 2 is after you put the request in the queue, the async variation will move on. The sync variation will not !!
If you are going to use a GCD for NSURLConnection you need to be careful on which thread you start the connection. Here is a SO link for more info. GCD with NSURLConnection

How does a serial dispatch queue guarantee resource protection?

//my_serial_queue is a serial_dispatch_queue
dispatch_async(my_serial_queue, ^{
//access a shared resource such as a bank account balance
[self changeBankAccountBalance];
});
If I submit 100 tasks that each access and mutate a bank account balance, I understand that a serial queue will execute each task sequentially, but do these tasks finish sequentially as well when using dispatch_async?
What if task #23 that I submit asynchronously to the serial queue takes a really long time to finish? Would task #24 start only when task #23 is done, or would task #24 begin before task #23 is done? If so, couldn't task #24 have the wrong bank account balance when it starts its job, thereby screwing up data integrity?
Thanks!!
Yes, a dedicated serial queue is a wonderful way to synchronize access to some resource shared amongst multiple threads. And, yes, with a serial queue, each task will wait for the prior one to complete.
Two observations:
While this sounds like a highly inefficient process, this is implicitly at the heart of any synchronization technique (whether queue-based or lock-based approach) whose goal is to minimize concurrent updates of a shared resource.
But in many scenarios the serial queue technique can yield significantly better performance than than other common techniques, such as simple mutex lock, NSLock, or the #synchronized directive. For a discussion on the alternative synchronization techniques, see the Synchronization section of the Threading Programming Guide. For a discussion about using queues in lieu of locks, see the Eliminating Lock-Based Code in the Migrating Away from Threads section of the Concurrency Programming Guide.
A variation of the serial queue pattern is to use the "reader-writer" pattern, where you create a GCD concurrent queue:
queue = dispatch_queue_create("identifier", DISPATCH_QUEUE_CONCURRENT);
You then perform reads using dispatch_sync, but you perform writes using dispatch_barrier_async. The net effective is to permit concurrent read operations, but ensure that writes are never performed concurrently.
If your resource permits concurrent reads, then the reader-writer pattern can offer further performance gain over that of a serial queue.
So, in short, while it seems inefficient to have task #24 wait for task #23, that is inherent in any synchronization technique where you strive to minimize concurrent updates of the shared resource. And GCD serial queues are a surprisingly efficient mechanism, often better than many simple locking mechanisms. The reader-writer pattern can, in some circumstance, offer even further performance improvements.
My original answer, below, was in response to the original question which was confusing titled "how does a serial dispatch queue guarantee concurrency?" In retrospect, this was just an accidental use of the wrong terms.
This is an interesting choice of words, "how does a serial dispatch queue guarantee concurrency?"
There are three types of queues, serial, concurrent, and the main queue. A serial queue will, as the name suggests, not start the next dispatched block until the prior one finished. (Using your example, this means that if task 23 takes a long time, it won't start task 24 until it's done.) Sometimes this is critical (e.g. if task 24 is dependent upon the results of task 23 or if both task 23 and 24 are trying to access the same shared resource).
If you want these various dispatched tasks to run concurrently with respect to each other, you use a concurrent queue (either one of the global concurrent queues that you get via dispatch_get_global_queue, or you can create your own concurrent queue using dispatch_queue_create with the DISPATCH_QUEUE_CONCURRENT option). In a concurrent queue, many of your dispatched tasks may run concurrently. Using concurrent queues requires some care (notably the synchronization of shared resources), but can yield significant performance benefits when implemented properly.
And as a compromise between these two approaches, you can use operation queues, which can be both concurrent, but in which you can also constrain how many of the operations on the queue will run concurrently at any given time by setting maxConcurrentOperationCount. A typical scenario where you'll use this is when doing background network tasks, where you do not want more than five concurrent network requests.
For more information, see the Concurrency Programming Guide.
man dispatch_queue_create says: “All memory writes performed by a block dispatched to a serial queue are guaranteed to be visible to subsequent blocks dispatched to the same queue.” Thus, serial queues are a good way to serializing access to mutable state to avoid race conditions.
do these tasks finish sequentially as well when using dispatch_async?
Yes. The queue dictates the execution policy, not how you queue the block.
In other words, if the queue is serial, queueing with async or sync doesn't change that. The only difference is: do I wait for this block to complete before continuing execution of the rest of the program? dispatch_async=no, dispatch_sync=yes.
What if task #23 that I submit asynchronously to the serial queue
takes a really long time to finish?
Nothing changes. A serial queue always waits for the previously dequeued block (#23) to complete before dequeuing and executing the next block (#24). If stalling the queue is a concern, you should implement a timeout inside your block code.

What is the difference between dispatch_get_global_queue and dispatch_queue_create?

I'm writing a moderately complex iOS program that needs to have multiple threads for some of its longer operations (parsing, connections to the network...etc). However, I'm confused as to what the difference is between dispatch_get_global_queue and dispatch_queue_create.
Which one should I use and could you give me a simple explanation of what the difference is in general? Thanks.
As the documentation describes, a global queue is good for concurrent tasks (i.e. you're going to dispatch various tasks asynchronously and you're perfectly happy if they run concurrently) and if you don't want to encounter the theoretical overhead of creating and destroying your own queue.
The creating of your own queue is very useful if you need a serial queue (i.e. you need the dispatched blocks to be executed one at a time). This can be useful in many scenarios, such as when each task is dependent upon the preceding one or when coordinating interaction with some shared resource from multiple threads.
Less common, but you will also want to create your own queue if you need to use barriers in conjunction with a concurrent queue. In that scenario, create a concurrent queue (i.e. dispatch_queue_create with the DISPATCH_QUEUE_CONCURRENT option) and use the barriers in conjunction with that queue. You should never use barriers on global queues.
My general counsel is if you need a serial queue (or need to use barriers), then create a queue. If you don't, go ahead and use the global queue and bypass the overhead of creating your own.
If you want a concurrent queue, but want to control how many operations can run concurrently, you can also consider using NSOperationQueue which has a maxConcurrentOperationCount property. This can be useful when doing network operations and you don't want too many concurrent requests being submitted to your server.
Just posted in a different answer, but here is something I wrote quite a while back:
The best way to conceptualize queues is to first realize that at the very low-level, there are only two types of queues: serial and concurrent.
Serial queues are monogamous, but uncommitted. If you give a bunch of tasks to each serial queue, it will run them one at a time, using only one thread at a time. The uncommitted aspect is that serial queues may switch to a different thread between tasks. Serial queues always wait for a task to finish before going to the next one. Thus tasks are completed in FIFO order. You can make as many serial queues as you need with dispatch_queue_create.
The main queue is a special serial queue. Unlike other serial queues, which are uncommitted, in that they are "dating" many threads but only one at time, the main queue is "married" to the main thread and all tasks are performed on it. Jobs on the main queue need to behave nicely with the runloop so that small operations don't block the UI and other important bits. Like all serial queues, tasks are completed in FIFO order.
If serial queues are monogamous, then concurrent queues are promiscuous. They will submit tasks to any available thread or even make new threads depending on system load. They may perform multiple tasks simultaneously on different threads. It's important that tasks submitted to the global queue are thread-safe and minimize side-effects. Tasks are submitted for execution in FIFO order, but order of completion is not guaranteed. As of this writing, there are only three concurrent queues and you can't make them, you can only fetch them with dispatch_get_global_queue.
edit: blog post expanding on this answer: http://amattn.com/p/grand_central_dispatch_gcd_summary_syntax_best_practices.html
One returns the existing global queue, the other creates a new one. Instead of using GCD, I would consider using NSOperation and operation queue. You can find more information about it in this guide. Typically, of you want the operations to execute concurrently, you want to create your own queue and put your operations in it.

Resources