这个方法是否安全

时间:2015-06-28 20:28:04

标签: c#

这个方法线程安全吗? 没有全局变量

public decimal ConvertToDecimal(string d)
{
    lock (LockObj)
    {
        return Math.Round(decimal.Parse(d), 2);
    }
}

修改 我的假设是2个线程进入方法,有2个不同的值,一个可以在另一个之前退出,我想这是一个不好的假设,有人能解释一下吗?

2 个答案:

答案 0 :(得分:2)

这个方法在没有lock语句的情况下是线程安全的:

public decimal ConvertToDecimal(string d)
{
    return Math.Round(decimal.Parse(d), 2);
}

没有共享状态或资源,所以没有什么需要用锁来保护。通过添加锁,您实际上无法并行执行此方法,因为锁保证一次只能有一个线程执行包含的代码。

答案 1 :(得分:1)

您似乎对线程的工作方式了解不足。

每次调用ConvertToDecimal时,都会在堆栈上创建一个新变量d:对于C#中的所有局部变量(在方法内创建的变量)都是如此。

这意味着调用ConvertToDecimal的每个线程都会获得自己的string d实例,当然,Math.Round中也会发生同样的情况。如果两个线程调用该方法,则会有两个string d个变量存活,每个线程只能访问自己的d

所以,没有必要锁:

public decimal ConvertToDecimal(string d)
{
    return Math.Round(decimal.Parse(d), 2);
}

事实上,正如凯尔指出的那样,通过将锁定放在那里,你就不可能并行执行该方法,因为每次线程到达这行代码:lock (LockObj)时,它都会检查是否存在是拥有该对象的锁的任何其他线程,如果有,它将停止执行,直到锁可用。

请注意,即使您尝试访问共享资源,也不一定需要使用锁;如果对该资源的所有访问都是读取操作(例如,常量),则可以让所有线程同时读取它而不进行锁定,这样就可以了。