Parallelisation

Now the Flow Update is on a separate thread, but we’re not really “multithreading” or saving any time yet, because we block the main thread for it to work:

To get the threads running in parallel, we can just stop the main thread from blocking, by changing the Update() function to:

    void Update()
    {
        ChildThreadWait.Set();
    }

This is very simple, and gets our threads looking like the following:

At least, that’s what we hope it’s going to do, but you can’t actually be sure. This is probably the most important part of multithreading, so we’ll work through a thought experiment to identify and resolve the issue.

Problems with Parallelisation

We can’t know how long that flow update is going to take. In particular, you can’t know how long it will take in relation to the other thread(s). You might think that it’ll probably finish in time; you might be able to test and see that it seems to be finished in time. But multithreaded systems are non-deterministic and you can’t really prove them safe by testing. They need to be safe by design.

For this example, let’s see what happens if the flow update takes longer than expected:

In the second frame, we have both threads reading and writing from the flow field at the same time, which is totally undefined and problematic behaviour. We also have the main thread trying to restart the child before it’s even finished, which again, is not OK.

Re-Synchronising the Threads

So let’s start by ensuring the child thread can’t take longer than the main thread, which we achieve by blocking the main thread at the beginning of the Update() function:

    void Update()
    {
        MainThreadWait.WaitOne();
        MainThreadWait.Reset();

        ChildThreadWait.Set();
    }

Note that on the first Update, we don’t wait as the MainThreadWait variable starts in its “set” state. But on subsequent frames, if the child thread is still running, the main thread will get held up, like so:

Now our two loops are in sync, but we still have both threads interacting with the same data in parallel. There are a few ways to deal with this, but the approach that I chose involves restructuring data so that nothing is directly shared between threads.

Simple Multithreading for Unity

Return to Blog