libuv的多线程之间传递消息
官网上给出的例子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 |
uv_loop_t *loop; |
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 |
void fake_download(uv_work_t *req) {
|
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 |
void print_progress(uv_async_t *handle, int status /*UNUSED*/) {
|
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 |
void after(uv_work_t *req, int status) {
|
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的多线程之间传递消息的更多相关文章
- EventBus的使用详解,功能为在Fragment,Activity,Service,线程之间传递消息
最近跟同事用到了EventBus的使用,之前不太了解EventBus,查阅资料发现EventBus还挺好用的,用法比较简单,下面就把我看到的关于EventBus的博客分享给大家,里面介绍了很多的使用详 ...
- 用WM_COPYDATA消息来实现两个进程之间传递数据
文着重讲述了如果用WM_COPYDATA消息来实现两个进程之间传递数据. 进程之间通讯的几种方法:在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯.常用的方法有 1.使用内存映射 ...
- 安卓中不同APP之间的消息通信
昨天在腾讯实习生招聘初试面试时面试官问道我关于两个APP之间相互通信的方式,当时自己回道到了contentProvider与BroadcastReceiver.但他接着问还有没有其它的方式,我跟他说可 ...
- Android消息传递之组件间传递消息
前言: 上篇学习总结了Android通过Handler消息机制实现了工作线程与UI线程之间的通信,今天来学习一下如何实现组件之间的通信.本文依然是为学习EventBus做铺垫,有对比才能进步,今天主要 ...
- Android开发--Service和Activity通过广播传递消息
Android的Service也运行在主线程,但是在服务里面是没法直接调用更改UI,如果需要服务传递消息给Activity,通过广播是其中的一种方法: 一.在服务里面发送广播 通过intent传送数据 ...
- javascript跨域传递消息 / 服务器实时推送总结
参考文档,下面有转载[非常好的两篇文章]: http://www.cnblogs.com/loveis715/p/4592246.html [跨源的各种方法总结] http://kb.cnblogs. ...
- 【Cocos2dx游戏开发】CCNotificationCenter传递消息和数据
在开发游戏的时候我们经常需要在层与层之间.场景与场景之间传递数据和消息,Cocos2dx框架应用观察者模式为我们封装了一个CCNotificationCenter类,也叫消息通知中心,它也是一个单例类 ...
- H5 页面与小程序之间 传递数据
H5 页面与小程序之间 传递数据 小程序里面的 H5页面与小程序之间怎么传递数据 webview与小程序之间的实时通信 webview主动发消息给小程序 webview可以利用jssdk提供的 wx. ...
- 大叔也说Xamarin~Android篇~Activity之间传递数组
回到目录 我们在开发应用程序时,不可能只使用一个Layout或者一个Activity,比如你个管理系统,要求用户先登陆然后再使用,这时你至少要有两个activity吧,先登陆一个,然后成功后需要跳到别 ...
随机推荐
- 2016-2017 ACM-ICPC, NEERC, Moscow Subregional Contest Problem L. Lazy Coordinator
题目来源:http://codeforces.com/group/aUVPeyEnI2/contest/229511 时间限制:1s 空间限制:512MB 题目大意: 给定一个n 随后跟着2n行输入 ...
- struts2--上传总结(限制大小和类型 非法上传的跳转)
网上有很多版本,鉴于实践出真知的态度 我自己探索了一番 struts版本:2.3.16 限制大小: struts2默认是2M 所以如果要扩大大小限制,应该先配一个全局struts2最大上限 <c ...
- asp.net如何实现负载均衡方案讨论
请注意,本文内容分多次修改,如需阅读,请阅读完整,因为早期的观点是不太合理的,后面由于水平进步,已经做了修改! 我的目标是我一个人搭建一个负载均衡网站.不接受这是网络部,或者运维,或者系统部的事情,所 ...
- 在pycharm中使用scrapy爬虫
目标在Win7上建立一个Scrapy爬虫项目,以及对其进行基本操作.运行环境:电脑上已经安装了python(环境变量path已经设置好), 以及scrapy模块,IDE为Pycharm .操作如下: ...
- DNS服务器的解析
---恢复内容开始--- DNS前言: 英特网作为域名和IP地址相互映射的一个分不式数据库,能够使用户更方便的访问互联网.而不用去记住能够被机器直接读取的IP地址的过程叫做域名解析(或主机名解析).D ...
- 爬虫学习之-sqlite3
SQLlte数据类型 SQLite能保存什么样的数据类型 ?? 可以保存空值.整数.浮点数.字符串和blob. 什么是blob ?? 是二进制大对象.例如图片.音乐.zip文件. 什么是游标 ?? 游 ...
- opencv 矩阵类数据的运算
参考:http://blog.sina.com.cn/s/blog_7908e1290101i97z.htmlhttp://blog.sina.com.cn/s/blog_afe2af380101bq ...
- Java 面试前的基础准备 - 01
使用这个在线网页编辑真的是不习惯,还是 windows live writer 好. 下面列一个清单用于最近的面试:( 清单是网上down的 ) static,final,transient 等关键字 ...
- 如何在VScode中添加代码片段
拿 VUE 举例,新建 VUE 文件,输入前缀,出现代码段 文件 ---> 首选项 ---> 用户代码片段 在输入框中输入 vue ,找到 vue.json ,然后在 vue.json ...
- 集成学习—boosting和bagging异同
集成学习 集成学习通过构建并结合多个学习器来完成学习任务.只包含同种类型的个体学习器,这样的集成是“同质”的:包含不同类型的个体学习器,这样的集成是“异质”的.集成学习通过将多个学习器进行结合,常可获 ...