Concurrency Overview
Concurrent programming is an essential feature in modern programming languages. The Cangjie programming language provides a preemptive thread model as its concurrent programming mechanism. When it comes to programming languages and threads, threads can be classified into two types: language threads and native threads.
- The former refers to a basic execution unit of a concurrency model in a programming language. The purpose of language threads is to shield underlying implementation details. Cangjie aims to provide a friendly, efficient, and unified concurrent programming interface for developers. As a result, the concept of Cangjie threads is introduced, enabling developers to write concurrent code without the care about differences between OS threads and user-mode threads.
- The latter refers to threads (usually OS threads) used in language implementation, which serve as specific implementation carriers of language threads. Different programming languages implement language threads in different ways. For example, some languages directly create threads via OS calls, meaning each language thread corresponds to a native thread. This implementation solution is generally referred to as a
1:1
thread model. Other languages may provide special thread implementation, which allows multiple language threads to be scheduled on multiple native threads. This is also referred to as aM:N
thread model, that is, M language threads are scheduled and executed on N native threads, where M and N are not necessarily equal. Currently, the Cangjie language also uses theM:N
thread model. Therefore, Cangjie threads are essentially user-mode lightweight threads that support preemption and are lighter than OS threads.
Each Cangjie thread is scheduled and executed by an underlying native thread, and multiple Cangjie threads can be executed by a single native thread. Each native thread continuously selects a ready Cangjie thread for execution. If Cangjie thread is blocked during execution (for example, waiting for a mutex to be released), the native thread suspends the current Cangjie thread, and selects next ready Cangjie thread. The blocked Cangjie thread will be scheduled and executed by the native thread after being ready again.
In most cases, developers only need to perform concurrent programming for Cangjie threads without considering these details. However, during cross-language programming, developers need to exercise caution when calling foreign functions that may be blocked, for example, I/O-related OS calls. In the following sample code the new thread calls the foreign function socket_read
. During program running, a native thread schedules and executes a Cangjie thread. After entering the foreign function, the system directly blocks the current native thread until the function execution is complete. When the native thread is blocked, other Cangjie threads cannot be scheduled for execution, which reduces the program throughput.
foreign socket_read(sock: Int64): CPointer<Int8>
let fut = spawn {
let sock: Int64 = ...
let ptr = socket_read(sock)
}
Note:
Unless otherwise specified, Thread is used to simply refer to Cangjie Thread in this document.