Put concisely, threading is the idea of a single program executing multiple lists of instructions simultaneously or nearly simultaneously. A single list of instructions is a "thread": a string of instructions that flows from one to the next in order. Multi-threading, then, is just what we call a program that has multiple strings of instructions going on at the same time. A program can spend time following one thread, jump to another thread, and come right back to the original thread from where it left off. What's more is that any given thread does not have to know that the program jumped to another thread in order to keep working properly, making it much easier to write multi-threaded programs than it sounds.
It is not strictly necessary to know how threading works to write a multi-threaded program. But if you're curious about what's going on behind the scenes, read on!
In every multi-threaded program, there is a little chunk of code hiding in the background called the scheduler. It is the job of the scheduler to manage which thread the program should be working on at any given time. There are two major ways of scheduling: preemtively or cooperatively. Cooperative multi-threading will follow a single thread until that thread yields control. That is, it will keep with a particular thread until the thread itself decides that it's OK for another thread to take over. A cooperative scheduler waits for this yield then decides which thread to run next. On the other end of the spectrum is preemptive multi-threading. Preemptive schedulers will interrupt a thread if it decides that the thread was taking too long to yield, then jump to a new thread. Threads under a preemptive scheduler can also choose to yield on their own before they are preempted.
In Robot Mesh Studio, the schedulers for Blockly, Python, and C++ are preemptive. This means that you don't have to know which commands yield and which commands don't in order to write a successful multi-threaded program. That being said, it can be helpful to know exactly what's going on to avoid some potential small irregularities. For example, if a thread has not yielded for some time and starts updating values used by another thread, but gets interrupted by the scheduler before it finishes. Some of the values would have been updated, and others would still be waiting until the scheduler came back to the first thread. How to deal with potential problems with being preempted differs depending on programming language and implementation.
There are not many commands that directly affect threading in PyMite Python, in keeping with its design goal of having a simple API. The scheduler does most of the work. There are some ways to suggest to the scheduler that it think about switching threads, but there is no way for a thread to explicitly yield or refuse to yield. There is a fairly good chance that the scheduler will move on if it thinks the thread will be waiting for a while, such as when sys.sleep is called. Without further ado, the commands: