在C#局部volatile变量变量、局部、volatile

2023-09-06 17:41:48 作者:夏日⊕樱花

在我的C#程序,我有方法,code:

In my C# program, I have got method code:

Object model;
int score;
for()
{
int tempScore=0;
Object tempModel=getModel();
//some interesting stuff modifying value of tempScore
if(tempScore>score)
    {
    score=tempScore;
    model=tempModel;
    }
}

我想用并行insted的正常的,但我怕我会遇到一些同步问题。我知道,我可以使用锁(型号),但我有什么可以做的简单类型的分数? 模型和评分方法是局部变量,因此它们线程之间共享。

I would like to use Parallel for insted of normal, but I'm afraid that i will encounter some synchronization issues. I know that I can use lock(model), but what can I do about simple type score? model and score are method local variables, therefore they are shared between threads.

推荐答案

如果您使用锁(型号),这并不意味着其他线程不会能够访问模式。它的意思是,两个线程不能在同一时间执行由保护的部分锁(型号)。正因为如此,你可以使用类似锁(型号)保护接分数了。

If you use lock (model), it doesn't mean that other threads won't be able to access model. What it means is that two threads won't be able to execute a section protected by lock (model) at the same time. Because of this, you could use something like lock (model) to protect access to score too.

但是,将不会在这种情况下工作。 锁定上的变量没有锁定,锁定的对象上,并修改该对象模式指的是循环。正因为如此,我瘦这里最好的选择是建立在另一个对象,并锁定:

But that wouldn't work in this case. lock doesn't lock on a variable, it locks on an object and you modify which object model refers to in the loop. Because of that, I thin the best option here is to create another object and lock on that:

object model;
int score;
object modelLock = new object();

Parallel.For(…, (…) =>
{
    int tempScore=0;
    Object tempModel=getModel();
    //some interesting stuff modifying value of tempScore
    lock (modelLock)
    {
        if(tempScore > score)
        {
            score=tempScore;
            model=tempModel;
        }
    }
});

如果你发现这是你需要的速度太慢(因为使用锁定确实有一定的开销,这可能会为你显著),你应该考虑使用的东西如 Thread.VolatileRead() Interlocked.CompareExchange() 。但要非常小心他们,因为这很容易让你的code巧妙地错了。

If you find out that this is too slow for your needs (because using lock does have some overhead, which might be significant for you), you should consider using something like Thread.VolatileRead() or Interlocked.CompareExchange(). But be very careful with them, because it's very easy to make your code subtly wrong.