如果某个其他方法正在运行,如何确保某个方法不会被执行?

时间:2012-12-17 18:46:29

标签: c# thread-safety

假设我有两种方法 -

getCurrentValue(int valueID)
updateValues(int changedComponentID)

这两个方法在不同的线程上独立调用同一个对象。

getCurrentValue()只是查找当前valueID的数据库。

Values”如果相应的components更改,则会更改。 updateValues()方法更新那些依赖于刚更改的组件的值,即changedComponentID。这是一个数据库操作,需要时间。

在进行此更新操作时,我不希望通过从数据库执行查找来返回过时值,但我想等到更新方法完成。同时,我不希望两个更新操作同时发生,或者在读取过程中发生更新。

所以,我想这样做 -

[MethodImpl(MethodImplOptions.Synchronized)]
public int getCurrentValue(int valueID)
     {
        while(updateOperationIsGoingOn)
          {
             // do nothing  
          }
        readOperationIsGoingOn = true;

        value = // read value from DB

        readOperationIsGoingOn = false; 
        return value;
     }

[MethodImpl(MethodImplOptions.Synchronized)]
public void updateValues(int componentID)
     {
         while(readOperationIsGoingOn)
          {
             // do nothing
          }
         updateOperationIsGoingOn = true;

         // update values in DB

         updateOperationIsGoingOn = false;
     }

我不确定这是否是一种正确的做法。有什么建议?谢谢。

3 个答案:

答案 0 :(得分:2)

在这两种方法之外创建一个静态对象。然后在该对象上使用lock语句;当一个方法访问受保护的代码时,另一个方法将等待锁定释放。

private static object _lockObj = new object();

public int getCurrentValue(int valueID)
     {
        object value;

        lock(_lockObj)
          {
           value = // read value from DB
          }
        return value;
     }

public void updateValues(int componentID)
     {
         lock(_lockObj)
          {
         // update values in DB

          }
     }

答案 1 :(得分:2)

这不是正确的方法。像这样你正在进行“主动等待”,有效地阻止你的CPU。

您应该使用锁定:

static object _syncRoot = new object();
public int getCurrentValue(int valueID)
{
    lock(_syncRoot)
    {
        value = // read value from DB
    }
}

public void updateValues(int componentID)
{
    lock(_syncRoot)
    {
        // update values in DB
    }
}

答案 2 :(得分:0)

private static readonly object _lock = new object();

public int getCurrentValue(int valueID)
{
    try
    {
        Monitor.Enter(_lock);
        value = // read value from DB
        return value;
    }
    finally
    {
        Monitor.Exit(_lock);
    }
}

public void updateValues(int componentID)
{
    try
    {
        Monitor.Enter(_lock);
        // update values in DB
    }
    finally
    {
        Monitor.Exit(_lock);
    }
}