【发布时间】:2017-10-15 10:02:51
【问题描述】:
无法理解 apress 书中关于 TPL 中线程本地与任务构造的误用案例的示例。
为什么没有达到预期结果的10000?
谁能对下面程序的程序流程给出更详细的解释,哪些行立即执行,一些行及时异步?执行的顺序和顺序?
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Listing_05 {
class BankAccount {
public int Balance {
get;
set;
}
}
class Listing_05 {
static void Main(string[] args) {
// create the bank account instance
BankAccount account = new BankAccount();
// create an array of tasks
Task<int>[] tasks = new Task<int>[10];
// create the thread local storage
ThreadLocal<int> tls = new ThreadLocal<int>(() => {
Console.WriteLine("Value factory called for value: {0}",
account.Balance);
return account.Balance;
});
for (int i = 0; i < 10; i++) {
// create a new task
tasks[i] = new Task<int>(() => {
// enter a loop for 1000 balance updates
for (int j = 0; j < 1000; j++) {
// update the TLS balance
tls.Value++;
}
// return the updated balance
return tls.Value;
});
// start the new task
tasks[i].Start();
}
// get the result from each task and add it to
// the balance
for (int i = 0; i < 10; i++) {
//added by myself to see any hints but still cannot have insights
Console.WriteLine("task {0} results {1}", i, tasks[i].Result);
//end of my editing
account.Balance += tasks[i].Result;
}
// write out the counter value
Console.WriteLine("Expected value {0}, Balance: {1}",
10000, account.Balance);
// wait for input before exiting
Console.WriteLine("Press enter to finish");
Console.ReadLine();
}
}
}
结果在使用 8 核 i7 cpu 的计算机中,应为 8 个线程。运行多次及以下是多次执行中的 2 次。
不了解程序如何以这种方式工作和表现
【问题讨论】:
-
是的,在提出上述问题之前,我只是在上面的链接上进行了谷歌搜索,但也许我是这个主题的新手,所以我很难理解程序为什么会这样。到目前为止,我的理解是 ThreadLocal 只是线程本地的数据。 Task 是声明性的,您描述未知工作线程要完成的任务。不知道线程本地初始化数据是否会由于 10 个任务中的一些重用已在 10 个任务中的一些任务中修改的相同线程数据而崩溃?有人能描述一下这个例子的执行是怎样的吗……应该推迟运行某些行吗?
-
@Cuda,您的价值工厂中有两个
account.Balance。两者都有权返回不同的结果。 -
任务通常在线程池提供的线程上运行。线程池最大的特点是它可以重用线程。因此,两个任务很容易最终使用相同的 ThreadLocal 变量,这是所提供示例中的一个错误。 AsyncLocal 类提供了一个有用的替代品。
-
无法保证调度程序将为您的代码使用多少线程
标签: c# multithreading thread-safety task-parallel-library