C#vs Java线程安全

Pie*_*Luc 0 c# thread-safety xamarin

在Java中我们可以做类似的事情

final string str = "I am a string";

Thread thread = new Thread(...{
    string str2 = "bla bla bla " + str;
});
Run Code Online (Sandbox Code Playgroud)

我不完全理解如何做到这一点,但重点是我需要声明str为最终在我的线程中访问它所以没有可变的腐败.

但现在我如何在C#中做到这一点

string str = "I am a string";

Task.Run(() => {
    string str2 = "bla bla " + str;
});
Run Code Online (Sandbox Code Playgroud)

它确实有效,但我不确定这是否正确.我正在使用Visual Studio for Xamarin.

Eri*_*ert 9

我们退一步吧.

在C#中创建lambda时,将外部变量捕获为变量:

int x = 123;
Action change = () => { Console.WriteLine(x); x = 345; };
Console.WriteLine(x); // 123
change(); // 123
Console.WriteLine(x); // 345
change(); // 345
x = 789;
change(); // 789
Console.WriteLine(x); // 345
Run Code Online (Sandbox Code Playgroud)

只有一个变量x,它由lambda和方法的激活共享.

这非常有用,但有些情况会让人感到非常困惑:

List<Action> actions = new List<Action>();
for(int x = 0; x < 10; ++x)
{
  actions.Add(() => { Console.WriteLine(x); });
}
actions[0](); // 10, surprise!
Run Code Online (Sandbox Code Playgroud)

只有一个变量x,所有lambda都共享它.

有些人想要第一个行为 - lambdas共享变量 - 但编写第二种程序的人想要第二种行为.他们希望lambdas捕获变量的当前值,而不是变量本身.

C#只需选择第一个选项即可解决此问题.Java通过使第一个场景非法来解决问题.如果您只能捕获永不改变的变量,那么您就没有将变量捕获为变量的好处或问题.

尽管存在缺点,我个人更喜欢C#选择.但两者都是合理的,合理的和有原则的.不同的语言设计师有不同的选择

该功能与线程安全本身无关.(虽然它有线程安全方面;在C#中通过lambdas在线程之间共享的变量不是易失性的.)相反,它是关于lambda捕获变量如何工作的设计决策.