LabVIEW uses preemptive and cooperative multithreading. Operating systems and processors with preemptive multithreading use a limited number of threads, so in certain cases, these systems return to using cooperative multithreading.
The execution system preemptively multitasks VIs using threads. However, a limited number of threads are available. For highly parallel applications, the execution system uses cooperative multitasking when available threads are busy. Also, the operating system handles preemptive multitasking between the application and other tasks.
The basic execution system maintains a queue of active tasks. For example, if you have three loops running in parallel, at any given time one task is running and the other two are waiting in the queue. Assuming all tasks have the same priority, one of the tasks runs for a certain amount of time. That task moves to the end of the queue, and the next task runs. When a task completes, the execution system removes it from the queue.
The execution system runs the first element of the queue by calling the generated code of the VI. At some point, the generated code of that VI checks with the execution system to see if the execution system assigns another task to run. If not, the code for the VI continues to run.
A few nodes or items on the block diagram are synchronous, meaning they do not multitask with other nodes. In a multithreaded application, they run to completion, and the thread in which they run is monopolized by that task until the task completes.
Property Nodes and Invoke Nodes used on control or application references, even for the Value property on a control reference, synchronize with the UI thread. Therefore, if the UI thread is busy, such as when displaying a large amount of data in a graph, the Property Node or Invoke Node will not execute until the UI thread completes its current work.
Shared library calls and computation functions run synchronously. Most analysis VIs and data acquisition VIs contain shared library calls and therefore run synchronously. Configure a single, non-reentrant VI to call the shared library to ensure that only one thread calls a non-reentrant shared library at a time. If the shared library is called from more than one non-reentrant VI, LabVIEW may return unexpected results.
Almost all other nodes are asynchronous. For example, structures, I/O functions, timing functions, and subVIs run asynchronously.
The Wait on Occurrence, Timing, GPIB, VISA, and Serial VIs and functions wait for the task to complete but can do so without holding up the thread. The execution system takes these tasks off the queue until their task is complete. When the task completes, the execution system puts it at the end of the queue. For example, when the user clicks a button on a dialog box the Three Button Dialog VI displays, the execution system puts the task at the end of the queue.
Deadlock occurs when two or more tasks are unable to complete because they are competing for the same system resource(s). An example of deadlock can be two applications that need to print a file. The first application, running on thread 1, acquires the file and locks it from other applications. The second application, in thread 2, does the same with the printer. In a non-preemptive environment, where the operating system does not intervene and free a resource, both applications wait for the other to release a resource, but neither releases the resource it already holds. One way to avoid deadlock is to configure VIs to access common resources in the same order.
In addition to running VIs, the execution system must coordinate interaction with the user interface. When you click a button, move a window, or change the value of a slide control, the execution system manages that activity and makes sure that the VI continues to run in the background.
The single-threaded execution system multitasks by switching back and forth between responding to user interaction and running VIs. The execution system checks to see if any user interface events require handling. If not, the execution system returns to the VI or accepts the next task off the queue.
When you click buttons or pull-down menus, the action you perform might take a while to complete because LabVIEW runs VIs in the background. LabVIEW switches back and forth between responding to your interaction with the control or menu and running VIs.
LabVIEW has six multiple execution systems that you can assign by selecting File»VI Properties and selecting Execution in the VI Properties dialog box. You can select from the following execution systems:
These execution systems provide some rough partitions for VIs that must run independently from other VIs. By default, VIs run in the Standard execution system.
The names Instrument I/O and Data Acquisition are suggestions for the type of tasks to place within these execution systems. I/O and data acquisition work in other systems, but you can use these labels to partition the application and understand the organization.
Execution systems are not responsible for managing the user interface. If a VI in one of these execution systems needs to update a control, the execution system passes responsibility to the user interface execution system. Assign the user interface execution system to VIs that contain a large amount of Property Nodes.
LabVIEW allocates a number of threads proportional to the number of processors on a machine. Each thread handles a task. For example, if a VI calls a shared library, the separate thread continues to run other VIs within that execution system. Because each execution system has a limited number of threads, tasks remain pending if the threads are busy.
Although VIs you write run correctly in the standard execution system, consider using another execution system. For example, if you are developing instrument drivers, you might want to use the instrument I/O execution system.
Even if you use the standard execution system, the user interface is still separated into its own thread. Any activities conducted in the user interface, such as drawing on the front panel, responding to mouse clicks, and so on, take place without interfering with the execution time of the block diagram code. Likewise, executing a long computational routine does not prevent the user interface from responding to mouse clicks or keyboard data entry.
Computers with multiple processors benefit even more from multithreading. On a single-processor computer, the operating system preempts the threads and distributes time to each thread on the processor. On a multiprocessor computer, threads can run simultaneously on the multiple processors so more than one activity can occur at the same time.