Android中线程同步之Mutex与Condtion的用法

2024-02-18 22:08

本文主要是介绍Android中线程同步之Mutex与Condtion的用法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android封装的同步类主要有MUTEX(AutoMutex)与Condition。本文分析如何使用他们,具体的实现参见《 Android中线程同步之MUTEX与Condtion的实现 》与《 pthread之MUTEX与Condition用法 》。
Keywords: Mutex, Condition Variable, AutoLock/AutoMutex, Android
关键字:互斥体、条件变量、自动锁/自动互斥体、Android

一、MUTEX


看MUTEX的外部接口定义(声明在frameworks/native/include/utils/Mutex.h中)
<图1 TODO>

1.1 构造/析构

[cpp]  view plain copy
  1. Mutex();  
  2. Mutex(const char* name);  
  3. Mutex(int type, const char* name = NULL);  
  4. ~Mutex();  

构造函数的区别在于参数:
- name 是为MUTEX指定名字,如不指定,缺省是NULL;
- type 是指定MUTEX的类型,有
[cpp]  view plain copy
  1. enum {  
  2.     PRIVATE = 0,  
  3.     SHARED = 1  
  4. };  
两种类型:PRIVATE是进程内部使用的;SHARED是适用于跨进程共享的。
如不指定,缺省是PRIVATE的类型。

1.2 功能函数

MUTEX有下面三个主要的功能函数:
[cpp]  view plain copy
  1. status_t    lock();  
  2. void        unlock();  
  3. status_t    tryLock();  

lock()    获取锁。如果获取就返回,否则挂起等待;
unlock()  释放锁;
tryLock() 如果当前锁可被获取(未被别的线程获取)就lock,否则也直接返回。返回值:0代表成功;其它值失败。与lock()的区别在于不论成功与否都会及时返回,而不是挂起等待。

线程在进入MUTEX保护的临界区之前通过lock()获取锁,获取锁之后可以执行临界区内的代码,退出临界区之后通过unlock释放锁。
某一时刻临界区内至多只有一个线程在执行,如果已有线程T1在执行,要进入临界区的其它线程T2在执行lock()之后就会被挂起等待;直到线程T1释放掉锁之后,线程T2才能获得锁进入临界区执行。

lock()/unlock()必须配合使用,tryLock()则要根据执行的结果有无获得锁而选择是否unlock()。

1.3 典型场景

[cpp]  view plain copy
  1. m_mutex.lock();  
  2. // CRITICAL AREA,需要保护的内容  
  3. m_mutex.unlock();  

二、Condition

看Condition的外部接口定义(声明在frameworks/native/include/utils/Condition.h中)
<图2 TODO>

2.1 构造/析构

[cpp]  view plain copy
  1. Condition();  
  2. Condition(int type);  
  3. ~Condition();  

构造函数的区别在于type参数:
- type 是指定Condition的类型,有
[cpp]  view plain copy
  1. enum {  
  2.     PRIVATE = 0,  
  3.     SHARED = 1  
  4. };  
两种类型:PRIVATE是进程内部使用的;SHARED是适用于跨进程共享的。
如不指定,缺省是PRIVATE的类型。

2.2 功能函数

Condition有下面四个主要的功能函数:
[cpp]  view plain copy
  1. status_t wait(Mutex& mutex);  
  2. status_t waitRelative(Mutex& mutex, nsecs_t reltime);  
  3. void signal();  
  4. void broadcast();  

wait() 等待条件变量(Condition Variable)
    Mutex作为参数,调用该函数之前该MUTEX必须已经被lock住。
    执行该函数,会unlock该MUTEX,并等待条件变量。如果不能获得该条件变量,就被挂起等待;获得了该条件变量,就重新lock住MUTEX并返回。而这些操作都是原子操作的。
    该函数执行之后,Mutex被重新lock住,所以执行函数之后,必须有Mutex的unlock操作。
waitRelative()与和wait()的区别是,会有一个等待超时时间,到了时间没有获得该条件变量也会返回,可通过返回值判断结果。
signal()和broadcast() 触发条件变量(Condition Variable)
    signal()和broadcast() 的区别是,signal()只允许等待该条件变量的一个线程获得;broadcast()允许等待该条件变量的所有线程获得并继续执行。
    signal()和broadcast() 执行之前也必须lock住Mutex,执行之后unlock Mutex。

2.3 典型场景

线程T1的执行:
[cpp]  view plain copy
  1. m_mutex.lock();     
  2. m_cond.wait(m_mutex);     
  3. m_mutex.unlock();  
线程T1通过条件变量在等待某个条件的满足。

线程T2执行:
[cpp]  view plain copy
  1. m_mutex.lock();     
  2. m_cond.signal();     
  3. m_mutex.unlock();  
线程T2在满足条件之后,通过条件变量通知条件满足。

三、Autolock/AutoMutex

Autolock是为了简化Mutex的使用而定义的,它也定义在frameworks/native/include/utils/Mutex.h中,封装了Mutex,并利用c++的构造与析构机制。
[cpp]  view plain copy
  1. Autolock(Mutex& mutex);  
  2. Autolock(Mutex* mutex);  
  3. ~Autolock();  

用法很简单,定义一个局部临时的AutoMutex变量,在该变量定义的地方,构造函数被自动调用,会执行Mutex的lock()操作;在该变量作用域结束的地方,析构函数会被自动调用,会执行Mutex的unlock操作。
所以,可以在需要Mutex保护的区域开始的地方定义一个AutoMutex变量即可,即可实现用Mutex对该区域的保护。

四、总结

本文简要介绍了Android中常用的同步机制Mutex(AutoMutex)、Condition的使用。后续文章(《 Android中线程同步之MUTEX与Condtion的实现 》与《 pthread之MUTEX与Condition用法 》)看它们是如何实现的。

这篇关于Android中线程同步之Mutex与Condtion的用法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/722609

相关文章

Mac备忘录怎么导出/备份和云同步? Mac备忘录使用技巧

《Mac备忘录怎么导出/备份和云同步?Mac备忘录使用技巧》备忘录作为iOS里简单而又不可或缺的一个系统应用,上手容易,可以满足我们日常生活中各种记录的需求,今天我们就来看看Mac备忘录的导出、... 「备忘录」是 MAC 上的一款常用应用,它可以帮助我们捕捉灵感、记录待办事项或保存重要信息。为了便于在不同

javascript fetch 用法讲解

《javascriptfetch用法讲解》fetch是一个现代化的JavaScriptAPI,用于发送网络请求并获取资源,它是浏览器提供的全局方法,可以替代传统的XMLHttpRequest,这篇... 目录1. 基本语法1.1 语法1.2 示例:简单 GET 请求2. Response 对象3. 配置请求

查看MySql主从同步的偏移量方式

《查看MySql主从同步的偏移量方式》:本文主要介绍查看MySql主从同步的偏移量方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 1.mysql的主从同步方案mysqlphp为了在实现读写分离,主库写,从库读mysql的同步方案主要是通过从库读取主库的binl

Go 语言中的 Struct Tag 的用法详解

《Go语言中的StructTag的用法详解》在Go语言中,结构体字段标签(StructTag)是一种用于给字段添加元信息(metadata)的机制,常用于序列化(如JSON、XML)、ORM映... 目录一、结构体标签的基本语法二、json:"token"的具体含义三、常见的标签格式变体四、使用示例五、使用

mysql中的group by高级用法详解

《mysql中的groupby高级用法详解》MySQL中的GROUPBY是数据聚合分析的核心功能,主要用于将结果集按指定列分组,并结合聚合函数进行统计计算,本文给大家介绍mysql中的groupby... 目录一、基本语法与核心功能二、基础用法示例1. 单列分组统计2. 多列组合分组3. 与WHERE结合使

MySQL 字符串截取函数及用法详解

《MySQL字符串截取函数及用法详解》在MySQL中,字符串截取是常见的操作,主要用于从字符串中提取特定部分,MySQL提供了多种函数来实现这一功能,包括LEFT()、RIGHT()、SUBST... 目录mysql 字符串截取函数详解RIGHT(str, length):从右侧截取指定长度的字符SUBST

SQL Server中的PIVOT与UNPIVOT用法具体示例详解

《SQLServer中的PIVOT与UNPIVOT用法具体示例详解》这篇文章主要给大家介绍了关于SQLServer中的PIVOT与UNPIVOT用法的具体示例,SQLServer中PIVOT和U... 目录引言一、PIVOT:将行转换为列核心作用语法结构实战示例二、UNPIVOT:将列编程转换为行核心作用语

Java中 instanceof 的用法详细介绍

《Java中instanceof的用法详细介绍》在Java中,instanceof是一个二元运算符(类型比较操作符),用于检查一个对象是否是某个特定类、接口的实例,或者是否是其子类的实例,这篇文章... 目录引言基本语法基本作用1. 检查对象是否是指定类的实例2. 检查对象是否是子类的实例3. 检查对象是否

Java中的内部类和常用类用法解读

《Java中的内部类和常用类用法解读》:本文主要介绍Java中的内部类和常用类用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录内部类和常用类内部类成员内部类静态内部类局部内部类匿名内部类常用类Object类包装类String类StringBuffer和Stri

Android NDK版本迭代与FFmpeg交叉编译完全指南

《AndroidNDK版本迭代与FFmpeg交叉编译完全指南》在Android开发中,使用NDK进行原生代码开发是一项常见需求,特别是当我们需要集成FFmpeg这样的多媒体处理库时,本文将深入分析A... 目录一、android NDK版本迭代分界线二、FFmpeg交叉编译关键注意事项三、完整编译脚本示例四