线程函数的行为与我预期的不同

twe*_*ypi 2 c# mono multithreading xamarin.ios

这是(大致)我所拥有的:

class A
{
    public bool IsInUpdate = false;
    public void Update()
    {
        IsInUpdate = true;

        //(...do stuff...)

        IsInUpdate = false;
    }
}

class B
{
    A a_inst;
    System.Threading.Thread physicsThread = null;

        void Draw()
        {
            physicsThread = new System.Threading.Thread(a_inst.Update);
            physicsThread.Start();
        }


    void Update()
    {
        while(physicsThread.IsAlive)
        {
            // Right here there can be cases where physicsThread.IsAlive is true but IsInUpdate is false, how does that happen?
        }

        (...do stuff...)
    }


}
Run Code Online (Sandbox Code Playgroud)

问题在代码的注释中.基本上物理线程实例说它还活着,但它调用的函数显然已经完成调用(可以看出bool设置为false).

任何想法为什么会这样?我想要做的就是确保在类A的线程更新函数执行之前,B类中的更新函数不会执行...

Mar*_*ell 6

既然IsInUpdate只是一个公共领域(而非volatile那个领域),就无法保证你看到的东西; 关于你所看到的内容的正常合理规则仅适用于单个线程,并且你没有保护任何这些数据.还有周围的边缘的情况下启动的条件,但我个人会使用或者lock(如果你需要等待它完成),或者也许Interlocked如果你只需要知道,如果它是积极的.

例如:

class A
{
    private readonly object syncLock = new object();
    public object SyncLock { get { return syncLock; } }
    public void Update()
    {
        lock(SyncLock)
        {

            //(...do stuff...)

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

void Update()
{
    lock(a_inst.SyncLock)
    {
        (...do stuff...)
    }
}
Run Code Online (Sandbox Code Playgroud)

通过以上,可以保证只有一个线程将有权随时锁定,所以,如果你能"做的东西",你知道,这是不是也正在运行的其他更新().如果你需要等待,还有Wait()/ Pulse()方法来防止锁,或者你可以使用ManualResetEvent/ 等门AutoResetEvent.

这样的事情lock也确保了线程之间正确的内存障碍,因此您可以看到正确的数据.