DEV Community

SameX
SameX

Posted on

High Concurrency IPC Communication Implementation: Asynchronous Invocation and Multithreading Processing in HarmonyOS

This article aims to deeply explore the technical details of the Huawei HarmonyOS Next system (up to API 12 as of now), and is summarized based on actual development practices. It mainly serves as a carrier for technical sharing and communication. Mistakes and omissions are inevitable. Colleagues are welcome to put forward valuable opinions and questions so that we can make progress together. This article is original content, and any form of reprint must indicate the source and the original author.
In today's mobile application development field, high - concurrency communication scenarios are becoming more and more common. Imagine that in a large - scale social application, thousands of users are online simultaneously, and they may be constantly sending messages, getting updates, uploading pictures, etc. This poses high requirements for inter - process communication (IPC). If the communication is not handled properly, it will be like a traffic jam, leading to application lag or even crash. Today, let's see how the IPC Kit in HarmonyOS copes with the challenges of high - concurrency communication through asynchronous invocation and multithreading processing.

Requirement Analysis and Design Architecture of High - Concurrency Communication

Performing Asynchronous Communication in a Multithreading Environment to Solve Communication Blocking and Performance Bottlenecks

In high - concurrency scenarios, the traditional synchronous communication method is like cars on a one - way street, passing one by one, which is very inefficient. For example, when a thread is waiting for the response of an IPC communication, it will be blocked all the time, and other tasks cannot be executed, which seriously affects the overall performance of the system. Asynchronous communication, on the other hand, is like a multi - lane highway, where multiple requests can be made simultaneously without interfering with each other.
To achieve asynchronous communication, the IPC Kit provides powerful functional support. We can utilize the asynchronous invocation mode so that the thread that initiates the communication does not have to wait for the result to return and can continue to execute other tasks. At the same time, combined with multithreading processing, different communication tasks are assigned to different threads, making full use of the advantages of multi - core processors and improving the concurrent processing ability of the system.
For example, in an online live streaming application, the video stream of the broadcaster needs to be transmitted to multiple viewers in real time. If synchronous communication is used, the broadcaster has to wait for the confirmation from the viewers for each frame of video sent, which will obviously cause serious delay. By using asynchronous communication and multithreading processing, the broadcaster can continuously send the video stream in one thread, while other threads are responsible for handling the feedback information from the viewers, such as likes and comments, so as to ensure the smooth playback of the video and improve the user experience.

Asynchronous Invocation Mode and Thread Management

Using the AsyncAdd Function and Threads to Handle Asynchronous Communication and Improve Communication Efficiency

The AsyncAdd function in the IPC Kit is an important tool for implementing asynchronous communication. It allows us to initiate a communication request in one thread and handle the response result in another thread.
The following is a simple sample code showing how to use the AsyncAdd function to achieve asynchronous communication (in C language as an example):

#include <IPCKit/ipc_kit.h>
#include <thread>
// Define the type of callback function after asynchronous communication is completed
typedef void (*AsyncCallback)(int result);
// Asynchronous add task function
void AsyncAdd(int a, int b, AsyncCallback callback) {
    // Create a thread to execute the asynchronous task
    std::thread t([a, b, callback]() {
        // Simulate a time - consuming IPC communication operation, here is just a simple addition operation
        int result = a + b;
        // Simulate communication delay, here it can be replaced with the actual IPC communication waiting time
        std::this_thread::sleep_for(std::chrono::seconds(2));
        // Call the callback function to return the result
        callback(result);
    });
    // Detach the thread to make it run independently
    t.detach();
}
// Callback function implementation
void OnAsyncResult(int result) {
    OH_LOG_INFO(LOG_APP, "Async result: %d", result);
}
int main() {
    // Initiate an asynchronous communication request
    AsyncAdd(3, 5, OnAsyncResult);
    // The main thread can continue to execute other tasks, here is just a simple print
    OH_LOG_INFO(LOG_APP, "Main thread is still running...");
    // To keep the program running for a while to observe the execution of the asynchronous task
    std::this_thread::sleep_for(std::chrono::seconds(5));
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

In the above code, the AsyncAdd function creates a new thread to execute the asynchronous task (here is a simple addition operation to simulate IPC communication), and returns the result through the callback function OnAsyncResult after the task is completed. The main thread will not be blocked after initiating the asynchronous request and can continue to perform other operations.

Data Synchronization and the Use of Shared Memory

Using Anonymous Shared Memory to Achieve Large - Data Transmission and Prevent Resource Competition

In high - concurrency communication, when large - data transmission is required, the ordinary IPC communication method may encounter performance bottlenecks. At this time, anonymous shared memory comes in handy. Anonymous shared memory is like a public warehouse, and multiple processes can access this warehouse simultaneously to store data in it, achieving efficient data sharing.
The following is a simple example code for reading and writing anonymous shared memory (in C language as an example):

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
// Define the size of the shared memory block
#define SHARED_MEM_SIZE 4096
int main() {
    // Create anonymous shared memory
    int fd = shmget(IPC_PRIVATE, SHARED_MEM_SIZE, IPC_CREAT | 0666);
    if (fd == -1) {
        perror("shmget");
        return -1;
    }
    // Map the shared memory to the process address space
    void *shared_mem = mmap(NULL, SHARED_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (shared_mem == MAP_FAILED) {
        perror("mmap");
        return -1;
    }
    // Create a child process
    pid_t pid = fork();
    if (pid == -1) {
        perror("fork");
        return -1;
    } else if (pid == 0) {
        // The child process writes data to the shared memory
        char *data = "Hello, shared memory!";
        memcpy(shared_mem, data, strlen(data) + 1);
        // Notify the parent process that the data has been written
        kill(getppid(), SIGUSR1);
    } else {
        // The parent process waits for the child process to write data
        sigset_t set;
        sigemptyset(&set);
        sigaddset(&set, SIGUSR1);
        sigwait(&set, NULL);
        // Read data from the shared memory
        char *read_data = (char *)shared_mem;
        printf("Read from shared memory: %s\n", read_data);
        // Unmap the shared memory
        if (munmap(shared_mem, SHARED_MEM_SIZE) == -1) {
            perror("munmap");
            return -1;
        }
        // Mark the shared memory segment to be destroyed
        if (shmctl(fd, IPC_RMID, NULL) == -1) {
            perror("shmctl");
            return -1;
        }
    }
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

In this example, the parent process and the child process interact with data through anonymous shared memory. The child process writes data to the shared memory and then notifies the parent process to read. This method avoids the performance loss caused by frequently transmitting large data through IPC communication, and at the same time realizes simple data synchronization through semaphores (here using the SIGUSR1 signal) to prevent resource competition.
Through the above introduction and code examples of asynchronous invocation and multithreading processing, and anonymous shared memory, we can see the powerful capabilities of the IPC Kit in high - concurrency scenarios. In actual development, we can flexibly use these technologies according to specific business requirements to build efficient and stable application programs. I hope everyone can keep making progress on the path of exploring HarmonyOS development, just like climbing a mountain, step by step, and finally reach the peak of technology! Haha, let's learn more interesting technical knowledge together next time! 😎

Top comments (0)