android condition 详细介绍

上一篇介绍了Mutex 的作用和实现,在多线程中,使用mutex 可以实现对全局变量的加锁保护,也就是在访问(读写)这个变量之前先要获取对应的锁,然后才能访问。在多线中还有这样的场景,某个线程需要等另外一个线程完成了某些操作,然后再“通知”这个线程往下执行,这就需要使用到condition,下面给出具体的实例。

frameworks/av/include/media/stagefright/foundation/ALooper.h

72      Mutex mLock;
73      Condition mQueueChangedCondition;
首先定义了mLock 和 mQueueChangedCondition 这两个成员变量。

frameworks/av/media/libstagefright/foundation/ALooper.cpp

194  bool ALooper::loop() {
195      Event event;
196  
197      {
198          Mutex::Autolock autoLock(mLock);  //在调用wait()或者waitRelative()必须先获取锁
199          if (mThread == NULL && !mRunningLocally) {
200              return false;
201          }
202          if (mEventQueue.empty()) {  //如果队列为空,则一直等待signal()
203              mQueueChangedCondition.wait(mLock); 
204              return true;
205          }
206          int64_t whenUs = (*mEventQueue.begin()).mWhenUs;
207          int64_t nowUs = GetNowUs();
208  
209          if (whenUs > nowUs) { 
210              int64_t delayUs = whenUs - nowUs;
211              mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll);  //等待signal(),如果超时也会返回
212  
213              return true;
214          }
215  
216          event = *mEventQueue.begin();
217          mEventQueue.erase(mEventQueue.begin());
218      }
...
227      return true;
228  }
上面这个是ALooper 中实现loop()的关键代码,Mutex::Autolock autoLock(mLock);  是为了保护里面对一些变量的访问是互质的。如果mEventQueue 队列是空,跑到mQueueChangedCondition.wait(mLock); 就会一直在那里等待,等待其他线程往这个队列里面丢消息,然后通知它去处理。所以这个loop()里面的逻辑就是判断队列里面是否有消息要处理,如果没有就阻塞在那里等待,其实是会让出cpu,如果队列里面有消息,也会先判断是否需要马上处理,如果不需要马上处理,则等待需要delay 的时间后再处理,最后的消息处理逻辑也很简单,就是出队列中取出需要处理的消息,然后调用这个消息绑定的handler函数处理。

168  void ALooper::post(const sp<AMessage> &msg, int64_t delayUs) {
169      Mutex::Autolock autoLock(mLock);
170  
171      int64_t whenUs;
172      if (delayUs > 0) {
173          whenUs = GetNowUs() + delayUs;
174      } else {
175          whenUs = GetNowUs();
176      }
177  
178      List<Event>::iterator it = mEventQueue.begin();
179      while (it != mEventQueue.end() && (*it).mWhenUs <= whenUs) {
180          ++it;
181      }
182  
183      Event event;
184      event.mWhenUs = whenUs;
185      event.mMessage = msg;
186  
187      if (it == mEventQueue.begin()) {
188          mQueueChangedCondition.signal();
189      }
190  
191      mEventQueue.insert(it, event);
192  }
post()就是把消息丢到队列里面,然后通知looper 线程来处理,这里面的具体逻辑是如果插入的消息放在最前面,则通知looper 线程处理,否则只是插入到队列中的指定位置。上面的设计类似于一个 等待-通知 模型,而实现的关键就是利用了Condition 。

system/core/include/utils/Condition.h

44  class Condition {
...
56      Condition();
57      Condition(int type);
58      ~Condition();
59      // Wait on the condition variable.  Lock the mutex before calling.
60      status_t wait(Mutex& mutex);
61      // same with relative timeout
62      status_t waitRelative(Mutex& mutex, nsecs_t reltime);
63      // Signal the condition variable, allowing exactly one thread to continue.
64      void signal();
65      // Signal the condition variable, allowing one or all threads to continue.
66      void signal(WakeUpType type) {
67          if (type == WAKE_UP_ONE) {
68              signal();
69          } else {
70              broadcast();
71          }
72      }
73      // Signal the condition variabl
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值