. Net 4.0 Parallel programming (7) data sharing in tasks (I)

Source: Internet
Author: User

In the previous articles, we have read part of Parallel Loop and Task. In multi-threaded programming, we have a pain point in data sharing and data synchronization in multiple threads. This Post and several subsequent Post articles will discuss common problems of data sharing in TPL and their common solutions.

Example
First, let's look at the following code:

Static void Main (string [] args)
{
Int Sum = 0;
Task [] tasks = new Task [10];
For (int I = 0; I <10; I ++)
{
Tasks [I] = new Task () =>
{
For (int j = 0; j <1000; j ++)
{
Sum = Sum + 1;
}
});
Tasks [I]. Start ();
}
Task. WaitAll (tasks );
Console. WriteLine ("Expected value {0}, Parallel value: {1 }",
10000, Sum );
Console. ReadLine ();
} The above Code is expected to get 10 threads to round-robin and accumulate the Sum data. According to our expectation, the calculated result should be: 10000, but let's look at the running result:

Why? As a matter of fact, we will understand that we perform the Sum operation in parallel in multiple threads, we can use a sequence chart to show the situation that the two threads simultaneously operate Sum (the statement in may be incorrect, please understand ):

 

The sum value obtained by Task 1 is 0, and Task 2 is also 0. After both tasks perform the 0 + 1 operation, the records are recorded in Sum, instead of accumulating the calculated information between our expected threads. In parallel programming, such data sharing problems are very common. In the above problem, we can solve this problem through sequential execution, but this is not what we want. After all, we still want to process it in parallel. A separate execution method is provided in TPL to solve this problem.

Separate execution
We can isolate the execution by passing the state parameter in the Task:

Static void Main (string [] args)
{
Int Sum = 0;
Task <int> [] tasks = new Task <int> [10];
For (int I = 0; I <10; I ++)
{
Tasks [I] = new Task <int> (obj) =>
{
Var start = (int) obj;
For (int j = 0; j <1000; j ++)
{
Start = start + 1;
}
Return start;
}, Sum );
Tasks [I]. Start ();
}
Task. WaitAll (tasks );
For (var I = 0; I <10; I ++)
{
Sum + = tasks [I]. Result;
}
Console. WriteLine ("Expected value {0}, Parallel value: {1 }",
10000, Sum );
Console. ReadLine ();
} In the above program, there is no data sharing during the execution of each Task. Each Task calculates its own value. Finally, we summarize the results of each Task. It seems that our problem has been solved, but we need to know that separation is not supported in. Net runtime. That is to say, every time we operate a Task, we must ensure that there is no data sharing between tasks, which is indeed troublesome. System. Threading. ThreadLocal is provided in. Net to create the separation.

ThreadLocal
ThreadLocal is a type that provides local thread storage. It can provide a separate instance for each thread to provide separate data results for each thread. In the above program, we can use TreadLocal:

Static void Main (string [] args)
{
Int Sum = 0;
Task <int> [] tasks = new Task <int> [10];
Var tl = new ThreadLocal <int> ();
For (int I = 0; I <10; I ++)
{
Tasks [I] = new Task <int> (obj) =>
{
Tl. Value = (int) obj;
For (int j = 0; j <1000; j ++)
{
Tl. Value ++;
}
Return tl. Value;
}, Sum );
Tasks [I]. Start ();
}
Task. WaitAll (tasks );
For (var I = 0; I <10; I ++)
{
Sum + = tasks [I]. Result;
}
Console. WriteLine ("Expected value {0}, Parallel value: {1 }",
10000, Sum );
Console. ReadLine ();
} Note that TreadLocal is for each thread rather than for each Task. The TreadLocal constructor provides an overloaded method to set the initial value of each thread Result. Let's take a look at the following example:

Static void Main (string [] args)
{
Int Sum = 0;
Task <int> [] tasks = new Task <int> [10];
Var tl = new ThreadLocal <int> () => {
Console. WriteLine (Sum );
Return Sum;
});
For (int I = 0; I <10; I ++)
{
Tasks [I] = new Task <int> () =>
{
For (int j = 0; j <1000; j ++)
{
Tl. Value ++;
}
Return tl. Value;
});
Tasks [I]. Start ();
}
Task. WaitAll (tasks );
For (var I = 0; I <10; I ++)
{
Sum + = tasks [I]. Result;
}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.