相关疑难解决方法(0)

是否可以从另一个线程观察部分构造的对象?

我经常听说在.NET 2.0内存模型中,写入始终使用释放围栏.这是真的?这是否意味着即使没有明确的内存屏障或锁定,也不可能在不同于创建它的线程上观察部分构造的对象(仅考虑引用类型)?我显然排除了构造函数泄漏this引用的情况.

例如,假设我们有不可变的引用类型:

public class Person
{
    public string Name { get; private set; }
    public int Age { get; private set; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}
Run Code Online (Sandbox Code Playgroud)

是否可以使用以下代码观察除"John 20"和"Jack 21"之外的任何输出,例如"null 20"或"Jack 0"?

// We could make this volatile to freshen the read, but I don't want
// to complicate the core of the question.
private Person person;

private void Thread1()
{
    while (true)
    {
        var personCopy = person; …
Run Code Online (Sandbox Code Playgroud)

.net c# multithreading memory-model thread-safety

27
推荐指数
1
解决办法
1125
查看次数

挥发性违反其主要工作?

根据MSDN:

volatile关键字表示某个字段可能被同时执行的多个线程修改.声明为volatile的字段不受编译器优化的约束,这些优化假定由单个线程进行访问.这可确保始终在字段中显示最新值.

请注意最后一句:

这可确保始终在字段中显示最新值.

但是,此关键字存在问题.

我已经读过它可以改变指令的顺序:

First instruction       Second instruction         Can they be swapped?
Read                         Read                         No
Read                         Write                        No
Write                       Write                         No 
Write                       Read                          Yes! <----
Run Code Online (Sandbox Code Playgroud)

这意味着John为一个易变的字段设置了一个值,后来 Paul想要阅读该字段,Paul正在获得旧的价值!

这是怎么回事?这不是主要的工作吗?

我知道还有其他解决方案,但我的问题是关于volatile关键字.

我(作为程序员)是否需要阻止使用此关键字 - 因为这种奇怪的行为?

.net c# multithreading volatile thread-safety

23
推荐指数
2
解决办法
1159
查看次数

半围栏和全围栏?

我一直在阅读,以Full fences防止任何类型的指令重新排序或缓存围栏(通过memoryBarrier)

然后我读到了volatile 哪些会产生"半围栏":

volatile关键字指示编译器在每次从该字段读取时生成一个获取栅栏,并在每次写入该字段时生成一个释放栅栏.

acquire-fence

获取栅栏可防止其他读/写在栅栏前移动;

release-fence

释放栅栏可防止在栅栏后移动其他读/写.

有人可以用简单的英语向我解释这两句话吗?

(围栏在哪里?)

编辑

在这里得到一些答案后 - 我已经制作了一幅可以帮助每个人的图画 - 我想.

http://i.stack.imgur.com/A5F7P.jpg 在此输入图像描述

.net c# multithreading

13
推荐指数
1
解决办法
3286
查看次数

构造函数可以被抢先一步吗?

是否有可能在C#中抢占构造函数?

例如,考虑代码:

public class A
{
    public bool ready = true;

    public A()
    {
        ready = false; // Point #1
        // Other initialization stuff
        ready = true; // Point #2
    }
}
Run Code Online (Sandbox Code Playgroud)

在代码中的其他地方,两个线程可以访问类型A的变量,第一个线程调用在#1点抢占的构造函数.然后第二个线程测试ready并发现它仍然是真的因此它做了一些坏事.

这种情况可能吗?

进一步来说:

  1. 构造函数可以被抢先一步吗?
  2. 如果是这样,这是否意味着应该有lock构造函数中的同步代码?
  3. 在构造函数退出后,构造的对象是否仅分配给共享变量,从而完全避免了这个问题?

c# multithreading

10
推荐指数
1
解决办法
282
查看次数

内存模型:防止存储释放和负载获取重新排序

众所周知,与Java的易失性不同,.NET的版本允许使用来自另一个位置的以下易失性读取来重新排序易失性写入.当它是一个问题时 MemoryBarier,建议放在它们之间,或者Interlocked.Exchange可以用来代替volatile写.

它可以工作,但MemoryBarier在高度优化的无锁代码中使用时可能成为性能杀手.

我想了一下,想出了一个主意.我希望有人告诉我,我是否采取了正确的方式.

所以,这个想法如下:

我们希望防止这两种访问之间的重新排序:

 volatile1 write

 volatile2 read
Run Code Online (Sandbox Code Playgroud)

从.NET MM我们知道:

 1) writes to a variable cannot be reordered with  a  following read from 
    the same variable
 2) no volatile accesses can be eliminated
 3) no memory accesses can be reordered with a previous volatile read 
Run Code Online (Sandbox Code Playgroud)

为了防止写入和读取之间不必要的重新排序,我们从刚刚写入的变量中引入了一个虚拟易失性读取:

 A) volatile1 write
 B) volatile1 read [to a visible (accessible | potentially shared) location]
 C) volatile2 read
Run Code Online (Sandbox Code Playgroud)

在这种情况下,B不能用A重新排序,因为它们都访问相同的变量, C不能用B重新排序,因为两个易失性读取不能相互重新排序,并且传递C …

.net c# performance volatile memory-model

5
推荐指数
1
解决办法
1060
查看次数

指令重新订购

我有一个关于C#/ .NET中法律指令重新排序的问题.

让我们从这个例子开始吧.我们在某个类中定义了此方法,其中_a,_b和_c是字段.

int _a;
int _b;
int _c;
void Foo()
{
   _a = 1; // Write 1
   _b = 1; // Write 2
   _c = 1; // Write 3
}
Run Code Online (Sandbox Code Playgroud)

我们的呼叫环境看起来像这样.

//memory operations
ClassInstance.Foo();
//memory operations
Run Code Online (Sandbox Code Playgroud)

我想知道当这个方法调用内联对函数调用时,什么样的法律指令重新排序是可能的.更具体地说,我想知道在Foo()中重新排序内存操作是否/何时合法,内存操作在其外部(来自我们之前的示例,//内存操作).

此外,函数调用(无内联)在某种意义上是"生成内存障碍".同样,在函数调用之前或之后发生的内存操作不能与函数调用中的内存操作重新排序.

如果是这样,当它被编译器内联时,它仍会有这种"内存屏障"行为吗?

.net c# memory-barriers

4
推荐指数
1
解决办法
1159
查看次数

实施Singleton ...带锁吗?

在多线程应用程序(ASP.NET MVC)上,我需要一个全局设置类,其中包含从Web.Config中获取的常量和值.

我想让这个类静态,作为单身......并锁定?

public static class Settings {

  public static LoggerSettings Logger;
  public static MailerSettings Mailer;

  public class LoggerSettings {
    public String Levels { get { return ConfigurationManager.AppSettings["Logger.Levels"]; } }
    public const String Report = "team@xyz.com";
  } // LoggerSettings

  public class MailerSettings {
    public String Contact { get { return ConfigurationManager.AppSettings["Mailer.Contact"]; } }
  } // MailerSettings

}
Run Code Online (Sandbox Code Playgroud)

我想我应该实行双锁?没有?

我不确定这样做的最好方法.我能帮忙吗?

谢谢你,米格尔

c#

1
推荐指数
2
解决办法
533
查看次数