官网上给出的例子http://nikhilm.github.io/uvbook/threads.html#inter-thread-communication,中文理解在后边

Inter-thread communication

Sometimes you want various threads to actually send each other messages while they are running. For example you might be running some long duration task in a separate thread (perhaps using uv_queue_work) but want to notify progress to the main thread. This is a simple example of having a download manager informing the user of the status of running downloads.

progress/main.c

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
uv_loop_t *loop;
uv_async_t async; int main() {
loop = uv_default_loop(); uv_work_t req;
int size = 10240;
req.data = (void*) &size; uv_async_init(loop, &async, print_progress);
uv_queue_work(loop, &req, fake_download, after); return uv_run(loop, UV_RUN_DEFAULT);
}

The async thread communication works on loops so although any thread can be the message sender, only threads with libuv loops can be receivers (or rather the loop is the receiver). libuv will invoke the callback (print_progress) with the async watcher whenever it receives a message.

Warning

It is important to realize that the message send is async, the callback may be invoked immediately after uv_async_send is called in another thread, or it may be invoked after some time. libuv may also combine multiple calls to uv_async_send and invoke your callback only once. The only guarantee that libuv makes is – The callback function is called at least once after the call to uv_async_send. If you have no pending calls to uv_async_send, the callback won’t be called. If you make two or more calls, and libuv hasn’t had a chance to run the callback yet, it may invoke your callback only once for the multiple invocations of uv_async_send. Your callback will never be called twice for just one event.

progress/main.c

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
void fake_download(uv_work_t *req) {
int size = *((int*) req->data);
int downloaded = 0;
double percentage;
while (downloaded < size) {
percentage = downloaded*100.0/size;
async.data = (void*) &percentage;
uv_async_send(&async); sleep(1);
downloaded += (200+random())%1000; // can only download max 1000bytes/sec,
// but at least a 200;
}
}

In the download function we modify the progress indicator and queue the message for delivery with uv_async_send. Remember: uv_async_send is also non-blocking and will return immediately.

progress/main.c

1
2
3
4
void print_progress(uv_async_t *handle, int status /*UNUSED*/) {
double percentage = *((double*) handle->data);
fprintf(stderr, "Downloaded %.2f%%\n", percentage);
}

The callback is a standard libuv pattern, extracting the data from the watcher.

Finally it is important to remember to clean up the watcher.

progress/main.c

1
2
3
4
void after(uv_work_t *req, int status) {
fprintf(stderr, "Download complete\n");
uv_close((uv_handle_t*) &async, NULL);
}

After this example, which showed the abuse of the data field, bnoordhuis pointed out that using the data field is not thread safe, and uv_async_send() is actually only meant to wake up the event loop. Use a mutex or rwlock to ensure accesses are performed in the right order.

这个也有中文版的翻译,可以网上搜到。

文中最后提到的uv_async_t.data不是线程安全的,我的理解如下:

在主线程中开启一个消息循环loop(uv_loop_t对象),然后为loop注册了一个异步消息监听器async(uv_async_t对象),其他线程就可以通过async给主线程发送消息。做法就是把数据保存在async下,然后将async发给loop,loop异步的获取async,然后从async中得到数据并处理。我想说的是,async对象只有一个,在传递的过程中没有副本,因此从发送消息到消息被获取并处理完毕,这期间async对象都是线程不安全的,应该加上同步机制来保证整个期间async对象只服务于一个其他线程。但是如果同步的话,那libuv提供的异步消息机制岂不没有用了?我们的多线程程序也会在此遇到瓶颈。

我的解决方法有两个:

1.其他线程在每次向主线程发送消息的时候,都新建一个async对象,并临时注册到loop里;当loop获取该async对象,处理完毕后,注销并并删除async对象

2.同时注册多个async对象,将他们保存在队列中。其他线程在向主线程发送消息时,互斥的获取其中一个async对象,等loop处理完该async对象后,将其互斥的插回队列。虽然这样也有同步操作,但它的同步周期大大减小,提高了线程并行度。

libuv的多线程之间传递消息的更多相关文章

  1. EventBus的使用详解,功能为在Fragment,Activity,Service,线程之间传递消息

    最近跟同事用到了EventBus的使用,之前不太了解EventBus,查阅资料发现EventBus还挺好用的,用法比较简单,下面就把我看到的关于EventBus的博客分享给大家,里面介绍了很多的使用详 ...

  2. 用WM_COPYDATA消息来实现两个进程之间传递数据

    文着重讲述了如果用WM_COPYDATA消息来实现两个进程之间传递数据. 进程之间通讯的几种方法:在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯.常用的方法有   1.使用内存映射 ...

  3. 安卓中不同APP之间的消息通信

    昨天在腾讯实习生招聘初试面试时面试官问道我关于两个APP之间相互通信的方式,当时自己回道到了contentProvider与BroadcastReceiver.但他接着问还有没有其它的方式,我跟他说可 ...

  4. Android消息传递之组件间传递消息

    前言: 上篇学习总结了Android通过Handler消息机制实现了工作线程与UI线程之间的通信,今天来学习一下如何实现组件之间的通信.本文依然是为学习EventBus做铺垫,有对比才能进步,今天主要 ...

  5. Android开发--Service和Activity通过广播传递消息

    Android的Service也运行在主线程,但是在服务里面是没法直接调用更改UI,如果需要服务传递消息给Activity,通过广播是其中的一种方法: 一.在服务里面发送广播 通过intent传送数据 ...

  6. javascript跨域传递消息 / 服务器实时推送总结

    参考文档,下面有转载[非常好的两篇文章]: http://www.cnblogs.com/loveis715/p/4592246.html [跨源的各种方法总结] http://kb.cnblogs. ...

  7. 【Cocos2dx游戏开发】CCNotificationCenter传递消息和数据

    在开发游戏的时候我们经常需要在层与层之间.场景与场景之间传递数据和消息,Cocos2dx框架应用观察者模式为我们封装了一个CCNotificationCenter类,也叫消息通知中心,它也是一个单例类 ...

  8. H5 页面与小程序之间 传递数据

    H5 页面与小程序之间 传递数据 小程序里面的 H5页面与小程序之间怎么传递数据 webview与小程序之间的实时通信 webview主动发消息给小程序 webview可以利用jssdk提供的 wx. ...

  9. 大叔也说Xamarin~Android篇~Activity之间传递数组

    回到目录 我们在开发应用程序时,不可能只使用一个Layout或者一个Activity,比如你个管理系统,要求用户先登陆然后再使用,这时你至少要有两个activity吧,先登陆一个,然后成功后需要跳到别 ...

随机推荐

  1. 全国城市一卡通一级TSM平台业务架构及意义

    [导读]TSM平台是一种具有鲜明行业属性的平台,因此,各行业都建立了本行业的TSM平台.为促进城市一卡通行业移动支付的快速发展,住房和城乡建设部也建立了全国城市一卡通行业一级TSM平台. 作为住建部标 ...

  2. Alpha发布_文案+美工

    团队名称:探路者 1蔺依铭:http://www.cnblogs.com/linym762/ 2张恩聚:http://www.cnblogs.com/zej87/ 3米赫:http://www.cnb ...

  3. HDU 5195 DZY Loves Topological Sorting 拓扑排序

    题目链接: hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5195 bc(中文):http://bestcoder.hdu.edu.cn/contests ...

  4. CNN误差反传时旋转卷积核的简明分析(转)

    CNN(卷积神经网络)的误差反传(error back propagation)中有一个非常关键的的步骤就是将某个卷积(Convolve)层的误差传到前一层的池化(Pool)层上,因为在CNN中是2D ...

  5. 2nd scrum站立会议

    scrum站立会议 站立会议是让团队成员每日面对面站立互相交流他们所承担任务的进度.它的一个附带好处是让同组成员了解到工作的情况.本质上是为了团队交流,不是会议报告. 站立会议的目的: 1.让整个团队 ...

  6. 【week10】规格说明书练习-吉林市1日游

    假设我们全班同学及教师去吉林省吉林市1日游,请为这次活动给出规格说明书. 版本:1.0 编订:于淼 团队:2016级计算机技术全体同学 日期:2016/11/19 1.引言 1.1 编写目的 1.2 ...

  7. iOS-开发者账号与证书

    0.开发者账号的申请 1.iOS-证书相关 2.iOS-证书申请 3.iOS-APNS证书申请与使用 4.iOS-App发布证书的申请与使用

  8. 访问控制列表-细说ACL那些事儿(ACL应用篇)

    1.ACL应用范围 通过前两期的ACL理论学习,大家知道ACL并不能单独完成控制网络访问行为或者限制网络流量的效果,而是需要应用到具体的业务模块才能实现上述功能. 那么ACL到底可以应用在哪些业务中呢 ...

  9. Linux内核分析第七周———可执行程序的装载

    Linux内核分析第七周---可执行程序的装载 李雪琦+原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/US ...

  10. 【agc008F】Black Radius

    Portal --> agc008F Solution  这题好神仙啊qwq疯狂orz看懂日文题解的sjk太强啦qwq ​   ​  首先我们要统计的东西,是一个涂黑的连通块,然后我们考虑找一个 ...