MyException - 我的异常网
当前位置:我的异常网» 操作系统 » 条件变量、自旋锁跟屏障

条件变量、自旋锁跟屏障

www.MyException.Cn  网友分享于:2013-11-19  浏览:0次
条件变量、自旋锁和屏障
    条件变量本身是由互斥量保护的,线程在改变条件状态之前必须首先锁住互斥量。
    下面一组函数可用来操作条件变量。
#include <pthread.h>
int pthread_cond_init( pthread_cond_t *restrict cond,
                       const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait( pthread_cond_t *restrict cond,
                            pthread_mutex_t *restrict mutex,
                            const struct timespec *restirct tsptr);

int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
                       /* 所有函数的返回值:若成功,返回 0;否则,返回错误编号 */

    pthread_cond_init 和 pthread_cond_destroy 函数分别用来初始化和销毁条件变量。参数 attr 可用来设置条件变量的属性,为 NULL 时表示使用默认属性。对于静态分配的条件变量,可以使用 PTHREAD_COND_INITIALIZER 常量来进行初始化。
    pthread_cond_wait 会等待条件变量变为真。传递给 pthread_cond_wait 的互斥量可对条件进行保护。调用者把锁住的互斥量传给函数,然后函数会自动把调用线程放到等待条件的线程列表上,并对互斥量解锁。这就关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道,这样线程就不会错过条件的任何变化。该函数返回时,互斥量会再次被锁住。pthread_cond_timedwait 函数同 pthread_cond_wait,不过提供了定时功能。如果到达指定的时刻条件还没出现,该函数将重新获取互斥量,然后返回错误 ETIMEDOUT。注意这两个函数在成功返回时,线程需要重新计算条件,因为另一个线程可能在运行并改变了条件。
    pthread_cond_signal 和 pthread_cond_broadcast 可用来通知线程条件已经满足,前者至少能唤醒一个等待该条件的线程,而后者则能唤醒所有等待该条件的线程。
    下面这个程序片段演示了如何结合条件变量和互斥量来同步线程。
#include <pthread.h>

struct msg{
	struct msg	*m_next;
	/* more stuff here */
};

struct msg	*workq;

pthread_cond_t	qready = PTHREAD_COND_INITIALIZER;
pthread_mutex_t	lock = PTHREAD_MUTEX_INITIALIZER;

void process_msq(void){
	for(;;){
		pthread_mutex_lock(&lock);
		while(workq == NULL)
			pthread_cond_wait(&qready, &lock);
		struct msg *mp = workq;
		workq = workq->m_next;
		pthread_mutex_unlock(&lock);
		/* now process mp */
	}
}

void enqueue_msg(struct msg *mp){
	pthread_mutex_lock(&lock);
	mp->m_next = workq;
	workq = mp;
	pthread_mutex_unlock(&lock);
	pthread_cond_signal(&qready);
}


    自旋锁与互斥量类似,但它不是通过休眠使进程阻塞,而是在获取锁前一直处于忙等待状态。因此它一般用于这种情况:锁被持有的时间短,而且线程并不希望在重新调度上花费太多的成本。
    自旋锁也有一组类似于互斥量的函数。
#include <pthread.h>
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
int pthread_spin_destroy(pthread_spinlock_t *lock);

int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
int pthread_spin_unlock(pthread_spinlock_t *lock);
                      /* 所有函数的返回值:若成功,返回 0;否则,返回错误编号 */

    pthread_spin_init 对自旋锁进行初始化,pthread_spin_destroy 则对其进行反初始化。只有一个属性是自旋锁持有的,该属性只在支持线程进程共享同步选项的平台上才用得到。pshared 参数表示进程共享属性,表明自旋锁是如何获取的。如果它为 PTHREAD_PROCESS_SHARED,则自旋锁能被可以访问锁底层内存的线程所获取,即使它们属于不同的进程;而如果它为 PTHREAD_PROCESS_PRIVATE,则自旋锁就只能被初始化该锁的进程内部的线程所访问。
    pthread_spin_lock 和 pthread_spin_trylock 可对自旋锁加锁。前者在获取锁前一直阻塞,后者如果不能获取锁就立即返回 EBUSY 错误而不会自旋。两种方式加的锁都可以使用 pthread_spin_unlock 进行解锁。

    屏障是用户协调多个用户并行工作的同步机制,它允许每个线程等待,直到所有的合作线程都达到某一点后再继续运行。pthread_join 函数就是一种屏障的例子。
    屏障也有一组操作函数。
#include <pthread.h>
int pthread_barrier_init(pthread_barrier_t *restrict barrier,
                 const pthread_barrierattr_t *restrict attr, unsigend int count);
int pthread_barrier_destroy(pthread_barrier_t *barrier);
                      /* 两个函数的返回值:若成功,返回 0;否则,返回错误编号 */
int pthread_barrier_wait(pthread_barrier_t *barrier);
    /* 返回值:若成功,返回 0 或者 PTHREAD_BARRIER_SERIAL_THREAD;否则,返回错误编号*/

    使用 pthread_barrier_init 初始化屏障时,可以用 count 参数指定在允许所有线程继续运行之前,必须到达屏障的线程数目。attr 参数是屏障属性,为 NULL 时表示使用默认属性。pthread_barrier_destroy 函数则用来释放分配给屏障的资源。
    pthread_barrier_wait 函数可用来等待其他线程赶上来。调用该函数的线程在屏障计数未满足条件时会进入休眠状态。如果该线程是最后一个调用该函数的线程,就满足了屏障计数,所有的线程都被唤醒。对于任意一个线程,该函数返回了 PTHREAD_BARRIER_SERIAL_THREAD,其他线程看到的返回值是 0。这使得一个线程可以作为主线程工作在其他所有线程已完成的工作结果上。一旦达到屏障计数,而且线程处于非阻塞状态,屏障就可以被重用。但除非在调用了 pthread_barrier_destroy 后又调用 pthread_barrier_init 修改了计数,否则屏障计数不会改变。

文章评论

“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
如何成为一名黑客
如何成为一名黑客
鲜为人知的编程真相
鲜为人知的编程真相
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
那些争议最大的编程观点
那些争议最大的编程观点
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
代码女神横空出世
代码女神横空出世
一个程序员的时间管理
一个程序员的时间管理
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
程序员必看的十大电影
程序员必看的十大电影
程序员的鄙视链
程序员的鄙视链
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
10个调试和排错的小建议
10个调试和排错的小建议
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
我的丈夫是个程序员
我的丈夫是个程序员
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
中美印日四国程序员比较
中美印日四国程序员比较
每天工作4小时的程序员
每天工作4小时的程序员
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
程序员应该关注的一些事儿
程序员应该关注的一些事儿
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
老程序员的下场
老程序员的下场
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
旅行,写作,编程
旅行,写作,编程
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
 程序员的样子
程序员的样子
程序员和编码员之间的区别
程序员和编码员之间的区别
编程语言是女人
编程语言是女人
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
为什么程序员都是夜猫子
为什么程序员都是夜猫子
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
Java程序员必看电影
Java程序员必看电影
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有