一、概述
在《线程编程常见API简介(上) 》中讲述了有关线程创建过程中常用的 API 的使用方法,本节继续讲述有关线程编程中常用 API 的使用方法。主要说明有关线程锁、线程局部变量等 API 的使用。
二、常用 API
1)线程锁 API
1.1)线程锁的初始化及销毁:pthread_mutex_init/pthread_mutex_destroy;在 acl 库中对应的 API 为:acl_pthread_mutex_init/acl_pthread_mutex_destroy。
- /**
- * 初始化线程锁对象
- * @param mutex {pthread_mutex_t*} 线程锁对象
- * @param attr {const pthread_mutexattr_t*} 线程锁属性对象
- * @return {int} 返回 0 表示成功,否则表示出错
- */
- int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
- /**
- * 销毁线程锁资源
- * @param mutex {pthread_mutex_t*} 线程锁对象,之前必须成功调用了
- * pthread_mutex_init 初始化了线程锁对象
- * @return {int} 返回 0 表示成功,否则表示出错
- */
- int pthread_mutex_destroy(pthread_mutex_t *mutex);
在线程初始化 API 中有一个线程锁属性对象:pthread_mutexattr_t *attr,该对象需要调用如下函数进行初始化及销毁:
1.2)线程锁属性对象的初始化及销毁:pthread_mutexattr_init/pthread_mutexattr_destroy。
- /**
- * 初始化线程锁属性对象
- * @param attr {pthread_mutexattr_t*} 线程锁属性对象
- * @return {int} 返回 0 表示成功,否则表示出错
- */
- int pthread_mutexattr_init(pthread_mutexattr_t *attr);
- /**
- * 销毁在初始化线程锁属性对象时分配的内部资源
- * @param attr {pthread_mutexattr_t*} 线程锁属性对象
- * @return {int} 返回 0 表示成功,否则表示出错
- */
- int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
除了上面所列出的初始化线程锁的方法外,在LINUX下台下还有一个快速对线程锁进行初始化的方法,如下声明线程锁变量即可:
- pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
1.3)线程锁加锁解锁 API:pthread_mutex_lock/pthread_mutex_unlock;在 acl 库中相应的表现形式为:acl_pthread_mutex_lock/acl_pthread_mutex_unlock。
- /**
- * 对线程锁加锁,一直至成功加锁或出错为止
- * @param mutex {pthread_mutex_t*} 线程锁对象
- * @return {int} 返回 0 表示成功加锁,否则表示出错
- */
- int pthread_mutex_lock(pthread_mutex_t *mutex);
- /**
- * 对加锁的线程锁解锁
- * @param mutex {pthread_mutex_t*} 线程锁对象
- * @return {int} 返回 0 表示成功解锁,否则表示出错,出错原因一般为:
- * 线程锁对象无效或当前该解锁线程并未拥有该线程锁
- */
- int pthread_mutex_unlock(pthread_mutex_t *mutex);
除了上面提到的阻塞式加锁方法,还有一个非阻塞式的加锁方法,调用 pthread_mutex_trylock API:
- /**
- * 尝试对线程锁加锁,如果该锁未被其它线程拥有,则本加锁线程便加锁
- * 成功,否则立即返回,并返回 EBUSY 表示该线程锁正被其它线程拥有
- * @param mutex {pthread_mutex_t*} 线程锁对象
- * @return {int} 返回 0 表示成功加锁,否则返回未成功加锁原因,一般
- * 原因有:线程锁对象无效,或该锁正被其它线程加锁
- */
- int pthread_mutex_trylock(pthread_mutex_t *mutex);
需要区分 pthread_mutex_lock 和 pthread_mutex_trylock 两种不同加锁方法,前者在成功加锁前会一直阻塞到其它线程释放锁(或出错了),后者则会立即返回,根据其返回值来检查是否成功加锁。
2)线程锁示例
下面以一个例子来简要说明一下上面线程锁的一些 API 的使用方法:
- #include <pthread.h>
- #include <assert.h>
- /* 全局静态线程锁 */
- static pthread_mutex_t __mutex;
- /* 全局静态变量 */
- static int __count = 0;
- static void *thread_fn(void *arg)
- {
- (void) arg; /* 避免编译器警告 */
- /* 对线程锁加锁 */
- assert(pthread_mutex_lock(&__mutex) == 0);
- __count++; /* 对全局静态变量加 1 */
- /* 对线程锁解锁 */
- assert(pthread_mutex_unlock(&__mutex) == 0);
- return NULL;
- }
- int main(void)
- {
- int i;
- pthread_t tids[10];
- /* 使用缺省的属性初始化线程锁 */
- assert(pthread_mutex_init(&__mutex, NULL) == 0);
- /* 创建 10 个子线程 */
- for (i = 0; i < 10; i++)
- assert(pthread_create(&tids[i], NULL, thread_fn, NULL) == 0);
- /* 等待所有子线程结束 */
- for (i = 0; i < 10; i++)
- assert(pthread_join(&tids[i], NULL) == 0);
- /* 判断全局静态变量最后的结果应该为 10 */
- assert(__count == 10);
- /* 销毁线程锁 */
- assert(pthread_mutex_destroy(&__mutex) == 0);
- return 0;
- }
3) 线程局部变量
有关线程局部变量的含义、API以及使用示例,请参考另外两篇文章:《多线程开发时线程局部变量的使用》,《再谈线程局部变量》。
好了,先说这些吧,下一节继续描述有关线程条件变量相关的 API 使用说明。