std.sync Package
Function Description
The sync package provides concurrent programming capabilities.
As more computers begin to use multi-core processors, concurrent programming becomes more important to give full play to the advantages of multi-core processors.
Different programming languages implement threads in different ways. In some programming languages, threads are created by calling an operating system (OS) API. In this case, each language thread corresponds to an OS thread, which is generally referred to as a 1:1 thread model. Some other programming languages provide a special thread implementation, which allows multiple language threads to be switched and executed in contexts of different quantities of OS threads. This implementation is also referred to as an M:N thread model. Specifically, M language threads are scheduled and executed on N OS threads, where M and N may not be equal.
The Cangjie programming language is intended to provide a user-friendly, efficient, and unified concurrent programming interface so that you do not need to care about the differences between concepts such as OS threads and user-mode threads. In addition, details of the underlying implementation are concealed. Therefore, we provide only the concept of Cangjie thread. The Cangjie thread is implemented using the M:N thread model. Therefore, it is essentially a user-mode lightweight thread that supports preemption and occupies less memory resources than the OS thread.
To execute a section of code concurrently, you only need to create one Cangjie thread.
To create a new Cangjie thread, you can use the keyword spawn and pass a lambda expression without formal parameters. The lambda expression is the code expected to be executed in the new thread.
Example:
Create a Cangjie thread using the keyword spawn
:
import std.sync.sleep
import std.time.Duration
main () {
spawn {
// Executed in the new thread
println("Thread: ${Thread.currentThread.id}")
}
// Executed in the main thread
println("Thread: ${Thread.currentThread.id}")
sleep(Duration.second)
0
}
The sync package provides different types of atomic operations, reentrant mutex and APIs thereof, and uses thread synchronization mechanism of shared variables and timers.
Atomic operations include operations of the integer type, Bool type, and reference type.
The integer types include Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, and UInt64.
Atomic operations of the integer type include basic operations such as read (load
) and write (store
), swap (swap
/compareAndSwap
), and arithmetic operation (fetchAdd
/fetchSub
). Note the following:
-
The returns of the swap operation and arithmetic operation are values not modified.
-
compareAndSwap
is used to check whether the value of the current atomic variable is equal to the specified value. If they are equal, the value is replaced with another value. If they are not equal, the value is not replaced.
Atomic operations of the Bool type and reference type provide only read, write, and swap operations. Note the following:
The atomic operations of the reference type are valid only for the reference type.
ReentrantMutex has many drawbacks in application. For example, you may forget to unlock, or when the mutex is held, an exception of being unable to automatically release the lock, is thrown. Therefore, the Cangjie programming language provides the keyword synchronized
for solving similar problems in combination with reentrantMutex.
A reentrant mutex instance is added after synchronized
to protect the subsequent modified code block. In this way, only one thread can execute the protected code at any time.
- Before entering a code block modified by
synchronized
, a thread automatically acquires a lock corresponding to theReentrantMutex
instance. If failing to acquire the lock, the current thread is blocked. - Before exiting the code block modified by
synchronized
(including use of control transfer expressions such asbreak
,continue
,return
, andthrow
in the code block), a thread automatically releases the lock of theReentrantMutex
instance.
Example:
Before entering the synchronized
code block, the thread of each for
loop automatically acquires a lock corresponding to the mtx
instance. Before exiting the code block, the thread releases the lock corresponding to the mtx
instance.
import std.sync.{ReentrantMutex, sleep}
import std.time.Duration
main () {
let mtx = ReentrantMutex()
let cnt = Box<Int64>(0)
for (_ in 0..10) {
spawn {
synchronized(mtx) {
cnt.value ++
println("count: ${cnt.value}")
}
}
}
sleep(Duration.second)
0
}
API List
Constant & Variable
Name | Description |
---|---|
DefaultMemoryOrder | Specifies the default memory order. For details, see MemoryOrder. |
Function
Name | Description |
---|---|
sleep(Duration) | Hibernates the current thread. |
Interface
Name | Description |
---|---|
IReentrantMutex | Provides the reentrant mutex interface. |
Class
Name | Description |
---|---|
AtomicBool | Provides functions related to atomic operations of the Bool type. |
AtomicInt16 | Provides functions related to atomic operations of the Int16 type. |
AtomicInt32 | Provides functions related to atomic operations of the Int32 type. |
AtomicInt64 | Provides functions related to atomic operations of the Int64 type. |
AtomicInt8 | Provides functions related to atomic operations of the Int8 type. |
AtomicOptionReference | Provides functions related to atomic operations of the reference type. |
AtomicReference | Provides functions related to atomic operations of the reference type. |
AtomicUInt16 | Provides functions related to atomic operations of the UInt16 type. |
AtomicUInt32 | Provides functions related to atomic operations of the UInt32 type. |
AtomicUInt64 | Provides functions related to atomic operations of the UInt64 type. |
AtomicUInt8 | Provides functions related to atomic operations of the UInt8 type. |
Barrier | Coordinates multiple threads to stop at a point of a program. |
Monitor | Blocks a thread and waits for a signal from another thread to resume. |
MultiConditionMonitor | Binds multiple condition variables to a mutex. |
ReentrantMutex | Provides functionality related to the reentrant lock. |
ReentrantReadMutex | Provides the read lock type in the reentrant read/write lock. |
ReentrantReadWriteMutex | Provides functionality related to the reentrant read/write lock. |
ReentrantWriteMutex | Provides the write lock type in the reentrant read/write lock. |
Semaphore | Provides semaphore-related functionality. |
SyncCounter | Provides the countdown counter functionality. |
Timer | Provides the timer functionality. |
Enumeration
Type | Description |
---|---|
MemoryOrder | Enumerates memory order types. |
ReadWriteMutexMode | Enumerates the read/write lock fairness modes. |
CatchupStyle | Enumerates the catch-up policies used by a repetitive task timer. |
Struct
Name | Description |
---|---|
ConditionID | Specifies the condition variable of a mutex. For details, see MultiConditionMonitor. |
Exception Class
Name | Description |
---|---|
IllegalSynchronizationStateException | Indicates an invalid synchronization state. |