1# Multithreaded Concurrency Overview
2
3Concurrency models are used to implement concurrent tasks in different scenarios. Common concurrency models are classified into shared memory models and message passing models.
4
5A typical message passing model is actor. It supports high-scale concurrency while eliminating a series of complex and occasional issues caused by locks.
6
7Currently, ArkTS provides two concurrency capabilities: TaskPool and Worker, both of which are implemented based on the actor model.
8
9For details about the comparison between the Actor concurrency model and the memory sharing concurrency model, see [Multithreaded Concurrency Model](#multithreaded concurrency model).
10
11## Multithreaded Concurrency Model
12
13In the memory sharing model, multiple threads execute complex tasks simultaneously. These threads depend on the same memory and have the permission to access the memory. Before accessing the memory, a thread must preempt and lock the memory. In this case, other threads have to wait for the thread to release the memory.
14
15In the actor model, each thread is an independent actor, which has its own memory. Actors trigger the behavior of each other through message transfer. They cannot directly access the memory space of each other.
16
17Different from the memory sharing model, the actor model provides independent memory space for each thread. As such, it avoids memory preemption and resulting function and performance problems.
18
19In the actor model, concurrent tasks and task results are transmitted through the inter-thread communication.
20
21This topic describes the differences between the two models when solving the producer-consumer problem.
22
23### Memory Sharing Model
24
25The following figure shows how the producer-consumer problem is resolved in the memory sharing model.
26
27![image_0000002001497485](figures/image_0000002001497485.png)
28
29To prevent dirty reads and writes caused by simultaneous access, only one producer or consumer can access a shared memory container at a time. This means that producers and consumers need to compete for the lock of the container. After a role obtains the lock, other roles have to wait.
30
31```ts
32// The pseudocode is used only as a logic example to help developers understand the differences between the memory sharing model and the Actor model.
33class Queue {
34  // ...
35  push(value: number) {}
36
37  empty(): boolean {
38    // ...
39    return true
40  }
41
42  pop(value: number) :number {
43    // ...
44    return value;
45  }
46}
47
48class Mutex {
49  // ...
50  lock(): boolean {
51    // ...
52    return true;
53  }
54
55  unlock() {
56
57  }
58}
59class BufferQueue {
60  queue: Queue = new Queue()
61  mutex: Mutex = new Mutex()
62  add(value: number) {
63    // Attempt to acquire the lock.
64    if (this.mutex.lock()) {
65      this.queue.push(value)
66      this.mutex.unlock()
67    }
68  }
69
70  take(value: number): number {
71    let res: number = 0;
72    // Attempt to acquire the lock.
73    if (this.mutex.lock()) {
74      if (this.queue.empty()) {
75        res = 1;
76      }
77      let num: number = this.queue.pop(value)
78      this.mutex.unlock()
79      res = num;
80    }
81    return res;
82  }
83}
84
85// Construct a globally shared memory segment.
86let g_bufferQueue = new BufferQueue()
87
88class Producer {
89  constructor() {
90  }
91  run() {
92    let value = Math.random()
93    // Initiate cross-thread access to the bufferQueue object.
94    g_bufferQueue.add(value)
95  }
96}
97
98class ConsumerTest {
99  constructor() {
100  }
101  run() {
102    // Initiate cross-thread access to the bufferQueue object.
103    let num = 123;
104    let res = g_bufferQueue.take(num)
105    if (res != null) {
106      // Add consumption logic.
107    }
108  }
109}
110
111function Main(): void {
112  let consumer: ConsumerTest = new ConsumerTest()
113  let producer1: Producer = new Producer()
114  for (let i = 0;i < 0;i++) {
115    // Simulate the startup of multiple threads to execute a production task.
116    // let thread = new Thread()
117    // thread.run(producer.run())
118    // consumer.run()
119  }
120}
121```
122
123
124### Actor Model
125
126The following figure shows how the producer-consumer problem is resolved by using **TaskPool** in the actor model.
127
128![image_0000001964697544](figures/image_0000001964697544.png)
129
130In the Actor model, different roles do not share memory. The producer thread and UI thread have their own VM instances. The two VM instances have exclusive memory and are isolated from each other. After producing the result, the producer sends the result to the UI thread through serialization. After consuming the result, the UI thread sends a new production task to the producer thread.
131
132```ts
133import { taskpool } from '@kit.ArkTS';
134
135// Cross-thread concurrent tasks
136@Concurrent
137async function produce(): Promise<number> {
138  // Add production logic.
139  console.info("producing...");
140  return Math.random();
141}
142
143class Consumer {
144  public consume(value: Object) {
145    // Add consumption logic.
146    console.info("consuming value: " + value);
147  }
148}
149
150@Entry
151@Component
152struct Index {
153  @State message: string = 'Hello World'
154
155  build() {
156    Row() {
157      Column() {
158        Text(this.message)
159          .fontSize(50)
160          .fontWeight(FontWeight.Bold)
161        Button() {
162          Text("start")
163        }.onClick(() => {
164          let produceTask: taskpool.Task = new taskpool.Task(produce);
165          let consumer: Consumer = new Consumer();
166          for (let index: number = 0; index < 10; index++) {
167            // Execute the asynchronous concurrent production task.
168            taskpool.execute(produceTask).then((res: Object) => {
169              consumer.consume(res);
170            }).catch((e: Error) => {
171              console.error(e.message);
172            })
173          }
174        })
175        .width('20%')
176        .height('20%')
177      }
178      .width('100%')
179    }
180    .height('100%')
181  }
182}
183```
184
185
186## TaskPool and Worker
187
188For details about the operation mechanisms and precautions, see [TaskPool Introduction](taskpool-introduction.md) and [Worker Introduction](worker-introduction.md). For details about their differences in the implementation features and use cases, see [Comparison Between TaskPool and Worker](taskpool-vs-worker.md).
189