Original: 8 Days of play parallel development--Seventh Day brief analysis task and thread pool
Actually speaking of the previous article, we have to say the task of knowledge also said almost, this one we began to understand the theoretical understanding of the "thread pool" and "task" between the relationship, whether it is
We are all inevitably talking about thread pooling, but after. NET 4.0, the thread pool engine takes into account future extensibility and leverages multicore microprocessors
Schema, as long as possible, we should try to use the task, not the thread pool.
First look at the structure of the task
We can see that Task.Factory.StartNew () appears to be equivalent to creating with ThreadPool.QueueUserWorkItem (), but notice that I am using the TPL form
Using the thread pool, knowing that the task appeared, has been advertised to PK the original thread with less effort and lower performance consumption.
Here is a brief analysis of the CLR thread pool, in fact, there is a thread pools called "Global queue" concept, each time we use the use of QueueUserWorkItem will produce a
Work items, and then work items are queued to the global queue, and the worker threads in the last thread pool are taken out as FIFO, similar to the following:
It is worth mentioning that, after the. NET 4.0, the "Global queue" uses a lock-free algorithm, compared to the previous version of the lock "global queue" brought about by the performance bottleneck has been greatly improved. So the mission
The thread pool of a delegate has not only a "global queue", but each worker thread has a "local queue", as follows
Our first reaction is certainly what the "local queue" does, and consider the situation where "work items" go into the "global queue" when we new a task, if our
The task executes very fast, then the "Global Queue" will be FIFO very often, then what is the way to alleviate it? When our task is nested, the "local queue" is going to have an effect,
For example, if we have 3 tasks in a task, then these 3 tasks will exist in the local queue.
1 class Program2 {3 Static voidMain (string[] args)4 {5 varTask = Task.Factory.StartNew (() =6 {7 varTask1 =Task.Factory.StartNew (RUN1);8 varTask2 =Task.Factory.StartNew (Run2);9 varTASK3 =Task.Factory.StartNew (RUN3);Ten OneTask.waitall (Newtask[] {task1, task2, task3}); A }); - - Console.read (); the } - - Public Static voidRun1 () {Thread.Sleep (100000); } - + Public Static voidRun2 () {Thread.Sleep (100000); } - + Public Static voidRun3 () {Thread.Sleep (100000); } A}
Can see, in fact, "local queue" played a role of shunt, also known as "task inline", "local queue" is the "LIFO" form, in fact, this form is
In order to improve performance, because the RUN3 is sent to the "local queue" may also exist in the CPU cache, so it is relatively faster to remove from the "local queue", the final effect
The result is that RUN3 should theoretically take precedence over run2,run1 first.
Now let us consider such a situation, for example, there are two people, one has done all the work assigned to himself, while the other person still has a lot of work, in human terms, the idle person should
To take over a busy person's work, similarly, "Thread 2" in the map ran out of all the tasks in the "local queue" and found that there were no "tasks" to run in the global queue, but
"Thread 1" also has run1,run2,run3, then "Thread 2" in the form of "FIFO" to Steal "Thread 1" inside the task.
From the above, we can see that these shunts and loads are beyond the ordinary threadpool.queueuserworkitem, so after. NET 4.0, we
Use TPL as much as possible and discard ThreadPool.
8 Days of play parallel development--Seventh Day brief analysis task and thread pool