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

相关文章

Python中你不知道的gzip高级用法分享

《Python中你不知道的gzip高级用法分享》在当今大数据时代,数据存储和传输成本已成为每个开发者必须考虑的问题,Python内置的gzip模块提供了一种简单高效的解决方案,下面小编就来和大家详细讲... 目录前言:为什么数据压缩如此重要1. gzip 模块基础介绍2. 基本压缩与解压缩操作2.1 压缩文

解读GC日志中的各项指标用法

《解读GC日志中的各项指标用法》:本文主要介绍GC日志中的各项指标用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、基础 GC 日志格式(以 G1 为例)1. Minor GC 日志2. Full GC 日志二、关键指标解析1. GC 类型与触发原因2. 堆

MySQL数据库中ENUM的用法是什么详解

《MySQL数据库中ENUM的用法是什么详解》ENUM是一个字符串对象,用于指定一组预定义的值,并可在创建表时使用,下面:本文主要介绍MySQL数据库中ENUM的用法是什么的相关资料,文中通过代码... 目录mysql 中 ENUM 的用法一、ENUM 的定义与语法二、ENUM 的特点三、ENUM 的用法1

JavaSE正则表达式用法总结大全

《JavaSE正则表达式用法总结大全》正则表达式就是由一些特定的字符组成,代表的是一个规则,:本文主要介绍JavaSE正则表达式用法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录常用的正则表达式匹配符正则表China编程达式常用的类Pattern类Matcher类PatternSynta

MySQL之InnoDB存储引擎中的索引用法及说明

《MySQL之InnoDB存储引擎中的索引用法及说明》:本文主要介绍MySQL之InnoDB存储引擎中的索引用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录1、背景2、准备3、正篇【1】存储用户记录的数据页【2】存储目录项记录的数据页【3】聚簇索引【4】二

mysql中的数据目录用法及说明

《mysql中的数据目录用法及说明》:本文主要介绍mysql中的数据目录用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、版本3、数据目录4、总结1、背景安装mysql之后,在安装目录下会有一个data目录,我们创建的数据库、创建的表、插入的

深度解析Python装饰器常见用法与进阶技巧

《深度解析Python装饰器常见用法与进阶技巧》Python装饰器(Decorator)是提升代码可读性与复用性的强大工具,本文将深入解析Python装饰器的原理,常见用法,进阶技巧与最佳实践,希望可... 目录装饰器的基本原理函数装饰器的常见用法带参数的装饰器类装饰器与方法装饰器装饰器的嵌套与组合进阶技巧

Mysql中isnull,ifnull,nullif的用法及语义详解

《Mysql中isnull,ifnull,nullif的用法及语义详解》MySQL中ISNULL判断表达式是否为NULL,IFNULL替换NULL值为指定值,NULLIF在表达式相等时返回NULL,用... 目录mysql中isnull,ifnull,nullif的用法1. ISNULL(expr) → 判

Java中的for循环高级用法

《Java中的for循环高级用法》本文系统解析Java中传统、增强型for循环、StreamAPI及并行流的实现原理与性能差异,并通过大量代码示例展示实际开发中的最佳实践,感兴趣的朋友一起看看吧... 目录前言一、基础篇:传统for循环1.1 标准语法结构1.2 典型应用场景二、进阶篇:增强型for循环2.

Python get()函数用法案例详解

《Pythonget()函数用法案例详解》在Python中,get()是字典(dict)类型的内置方法,用于安全地获取字典中指定键对应的值,它的核心作用是避免因访问不存在的键而引发KeyError错... 目录简介基本语法一、用法二、案例:安全访问未知键三、案例:配置参数默认值简介python是一种高级编