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 the ReentrantMutex 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 as break, continue, return, and throw in the code block), a thread automatically releases the lock of the ReentrantMutex 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

NameDescription
DefaultMemoryOrderSpecifies the default memory order. For details, see MemoryOrder.

Function

NameDescription
sleep(Duration)Hibernates the current thread.

Interface

NameDescription
IReentrantMutexProvides the reentrant mutex interface.

Class

NameDescription
AtomicBoolProvides functions related to atomic operations of the Bool type.
AtomicInt16Provides functions related to atomic operations of the Int16 type.
AtomicInt32Provides functions related to atomic operations of the Int32 type.
AtomicInt64Provides functions related to atomic operations of the Int64 type.
AtomicInt8Provides functions related to atomic operations of the Int8 type.
AtomicOptionReferenceProvides functions related to atomic operations of the reference type.
AtomicReferenceProvides functions related to atomic operations of the reference type.
AtomicUInt16Provides functions related to atomic operations of the UInt16 type.
AtomicUInt32Provides functions related to atomic operations of the UInt32 type.
AtomicUInt64Provides functions related to atomic operations of the UInt64 type.
AtomicUInt8Provides functions related to atomic operations of the UInt8 type.
BarrierCoordinates multiple threads to stop at a point of a program.
MonitorBlocks a thread and waits for a signal from another thread to resume.
MultiConditionMonitorBinds multiple condition variables to a mutex.
ReentrantMutexProvides functionality related to the reentrant lock.
ReentrantReadMutexProvides the read lock type in the reentrant read/write lock.
ReentrantReadWriteMutexProvides functionality related to the reentrant read/write lock.
ReentrantWriteMutexProvides the write lock type in the reentrant read/write lock.
SemaphoreProvides semaphore-related functionality.
SyncCounterProvides the countdown counter functionality.
TimerProvides the timer functionality.

Enumeration

TypeDescription
MemoryOrderEnumerates memory order types.
ReadWriteMutexModeEnumerates the read/write lock fairness modes.
CatchupStyleEnumerates the catch-up policies used by a repetitive task timer.

Struct

NameDescription
ConditionIDSpecifies the condition variable of a mutex. For details, see MultiConditionMonitor.

Exception Class

NameDescription
IllegalSynchronizationStateExceptionIndicates an invalid synchronization state.