2010-10-31 18 views
1

我想知道,如果我有一个多核处理器,并且我有多个线程,如果2个或更多的线程同时访问一个变量,程序可能会崩溃吗?我怎样才能暂时阻止一个变量,以便同时访问受到限制?线程访问正在使用的变量

问候, 亚历Badescu

+0

在特殊情况下,在任何线程启动之前初始化变量,并且线程只读取变量,则不需要任何同步。 – Dialecticus 2010-10-31 10:27:10

回答

1

它是可能的,如果2个或更多的线程在同一时间

这是不可能的,程序会崩溃访问变量,程序会崩溃。它可能不会像你期望的那样表现,因为它会造成竞争状况。

我怎样才能阻止暂时一个变量,以便同时使多个访问限制

使用lock statement

+0

谢谢!但是,如果我锁定一个对象,并且某些流需要写入该对象,则该流将等待该对象被解锁并正常继续?或者它会尝试访问,看到它无法访问并跳过此任务? – Alex 2010-10-31 10:04:00

+1

如果另一个线程试图锁定目前正在锁定这个其他线程将阻塞等待直到第一个线程释放锁的一些对象。 – 2010-10-31 10:04:29

+0

啊,你已经开悟了我!问候! – Alex 2010-10-31 10:07:06

2

您可以使用lock关键字或Interlocked类。

例如

public class Foo 
{ 
    private object barLock = new object(); 
    private int bar; 

    public void Add(int x) 
    { 
     lock (barLock) 
     { 
      this.bar += x; 
     } 
    } 
} 

public class Foo 
{ 
    private int bar; 

    public void Increment() 
    { 
     Interlocked.Increment(ref x); 
    } 
} 

我会用Interlocked类只要有可能,因为这通常是最简单和最有效的(最快)的方式来做到这一点,但只有某些操作照顾。对于更复杂的操作,lock是要走的路。

我建议不要使用C#volatile关键字,因为这会影响全部访问给定字段。更好地坚持更高层次的概念,如lockInterlocked

1

使用lock声明(这实在是语法糖的Monitor.Enter /退出)

5

它不会崩溃,但它可能会给出错误的结果。

要阻止,你需要确保每一个访问是通过一个锁声明保护的一台监视器上:

private readonly object monitor = new object(); 
private int sharedVariable; 

public void MethodThatSetsVariable() 
{ 
    lock (monitor) 
    { 
     sharedVariable = 5; 
    } 
} 

public void MethodThatReadsVariable() 
{ 
    int foo; 
    lock (monitor) 
    { 
     foo = sharedVariable; 
    } 
    // Use foo now 
} 

替代方案:

  • 使用volatile变量,虽然具体行为volatile很难理解。 (嗯,这是超越我,反正。)
  • Interlocked类的使用方法

注意,这两个是最适合当它只是一个单一的共享变量,你有兴趣。当你必须访问一组变量,确保你只能看到完全一致的状态,锁是最简单的方法。

另一种选择 - 和如果在所有可能优选的 - 是为了避免需要在第一位置可变的共享状态。这并不总是可能的,至少在没有对消息传递架构进行完全重新设计的情况下 - 但是在可能的情况下,这是值得的。不可变的类型可以帮助更容易实现。