# 线程安全函数使用问题汇总

#### 问题现象

1.  在使用napi\_create\_threadsafe\_function进行数据传递时，回调内会拿到脏数据，应该怎么处理？
2.  napi\_threadsafe\_function在什么情况下会被意外释放？
3.  如何实现Native线程调用ArkTS线程？
4.  在Native线程中创建线程安全函数并调用，会有概率闪退，是什么原因？
5.  如果在ArkTS侧定义了回调方法想要在Native侧线程安全函数中使用，应该传入napi\_create\_threadsafe\_function的第几个参数？

#### 背景知识

线程安全函数主要用于在多个线程之间共享和调用，而不会出现竞争条件或死锁。例如以下场景：

*   异步计算：如果需要进行耗时的计算或IO操作，可以创建一个线程安全的函数，将计算或IO操作放在另一个线程中执行，避免阻塞主线程，提高程序的响应速度。
*   数据共享：如果多个线程需要访问同一份数据，可以创建一个线程安全的函数，确保数据的读写操作不会发生竞争条件或死锁等问题。
*   多线程编程：如果需要进行多线程编程，可以创建一个线程安全的函数，确保多个线程之间的通信和同步操作正确无误。

#### 解决方案

1.  在数据传递过程使用深拷贝模式进行传递，确保数据的完整性。
2.  当引用计数变为0或者调用napi\_release\_threadsafe\_function时指定NATIVE\_TSFUNC\_ABORT时，线程安全函数会被意外释放。
    
    其中，因为线程安全函数被创建时初始引用计数是1，如果没有使用napi\_acquire\_threadsafe\_function增加引用计数，不会被系统主动回收。
    
3.  在Native侧创建ArkTS线程安全函数后，在子线程中通过napi\_call\_function接口调用ArkTS方法，参考实现Native侧子线程与UI主线程通信。
4.  napi\_create\_threadsafe\_function是用于处理多线程之间的共享和调用，必须在主线程创建，在子线程创建会发生莫名崩溃。
    
    同时，napi\_env不能在不同线程之间共享或传递，缓存napi\_env并在不同线程中使用，会导致线程安全问题，因此不建议缓存env在非主线程中使用，参考：napi\_env禁止缓存的原因是什么。
    
5.  napi\_create\_threadsafe\_function回调函数相关参数说明如下：
    
    | 参数名 | 参数位置 | 参数说明 |
    | --- | --- | --- |
    | func | 2 | ArkTS应用侧传入的回调接口callback，可为空。当该值为nullptr时，下文call_js_cb不能为nullptr。反之，亦然。两者不可同时为空 |
    | call_js_cb | 10 | 子线程需要处理的线程安全回调任务，类似于异步工作项中的complete回调。当调用napi_call_threadsafe_function后，被抛到ArkTS主线程EventLoop中，等待调度执行。当该值为空时，系统将会调用默认回调接口 |
    
    若在ArkTS侧定义了回调方法，可以传入第二个参数进行调用。