linux多线程服务器编程(全方面了解linux多线程服务)(9/13)

来源:国外服务器 在您之前已被浏览:1 次
导读:目前正在解读《linux多线程服务器编程(全方面了解linux多线程服务)(9/13)》的相关信息,《linux多线程服务器编程(全方面了解linux多线程服务)(9/13)》是由用户自行发布的知识型内容!下面请观看由(国外主机 - www.2bp.net)用户发布《linux多线程服务器编程(全方面了解linux多线程服务)(9/13)》的详细说明。
笨笨网美国主机,w ww.2 b p .n e t

linux多线程服务器编程(全方面了解linux多线程服务)(9/13)


7.3.2条件变量的等待

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

为什么这两个接口中有互斥锁?

条件不会无缘无故地突然变得满足了, 必然会牵扯到共享数据的变化。 所以一定要有互斥锁来保护。 没有互斥锁, 就无法安全地获取和修改共享数据。

同步并没有保证互斥,而保证互斥是使用到了互斥锁。

pthread_mutex_lock(&m)while(condition_is_false){pthread_mutex_unlock(&m);//解锁之后, 等待之前, 可能条件已经满足, 信号已经发出, 但是该信号可能会被错过cond_wait(&cv);pthread_mutex_lock(&m);}

上面的解锁和等待不是原子操作。 解锁以后, 调用cond_wait之前,如果已经有其他线程获取到了互斥量, 并且满足了条件, 同时发出了通知信号, 那么cond_wait将错过这个信号, 可能会导致线程永远处于阻塞状态。 所以解锁加等待必须是一个原子性的操作, 以确保已经注册到事件的等待队列之前, 不会有其他线程可以获得互斥量。

那先注册等待事件, 后释放锁不行吗? 注意, 条件等待是个阻塞型的接口, 不单单是注册在事件的等待队列上, 线程也会因此阻塞于此, 从而导致互斥量无法释放, 其他线程获取不到互斥量, 也就无法通过改变共享数据使等待的条件得到满足, 因此这就造成了死锁。

pthread_mutex_lock(&m);while(condition_is_false)pthread_cond_wait(&v,&m);//此处会阻塞/*如果代码运行到此处, 则表示我们等待的条件已经满足了,*并且在此持有了互斥量*//*在满足条件的情况下, 做你想做的事情。*/pthread_mutex_unlock(&m);

pthread_cond_wait函数只能由拥有互斥量的线程来调用, 当该函数返回的时候, 系统会确保该线程再次持有互斥量, 所以这个接口容易给人一种误解, 就是该线程一直在持有互斥量。 事实上并不是这样的。 这个接口向系统声明了我在PCB等待序列中之后, 就把互斥量给释放了。 这样其他线程就有机会持有互斥量,操作共享数据, 触发变化, 使线程等待的条件得到满足。

pthread_cond_wait内部会进行解锁逻辑,则一定要先放到PCB等待序列中,再进行解锁。while(condition_is_false)pthread_cond_wait(&v,&m);//此处会阻塞if(condition_is_false)pthread_cond_wait(&v,&m);//此处会阻塞

唤醒以后, 再次检查条件是否满足, 是不是多此一举?

因为唤醒中存在虚假唤醒(spurious wakeup) , 换言之,条件尚未满足, pthread_cond_wait就返了。 在一些实现中, 即使没有其他线程向条件变量发送信号, 等待此条件变量的线程也有可能会醒来。

条件满足了发送信号, 但等到调用pthread_cond_wait的线程得到CPU资源时, 条件又再次不满足了。 好在无论是哪种情况, 醒来之后再次测试条件是否满足就可以解决虚假等待的问题。

pthread_cond_wait内部实现逻辑:

将调用pthread_cond_wait函数的执行流放入到PCB等待队列当中

解锁

等待被唤醒

被唤醒之后:

1、从PCB等待队列中移除出来

2、抢占互斥锁

情况1:拿到互斥锁,pthread_cond_wait就返回了

情况2:没有拿到互斥锁,阻塞在pthread_cond_wait内部抢锁的逻辑中

当阻塞在pthread_cond_wait函数抢锁逻辑中时,一旦执行流时间耗尽,意味着线程就被切换出来了,程序计数器就保存的是抢锁的指令,上下文信息保存的就是寄存器的值

当再次拥有CPU资源后,恢复抢锁逻辑

直到抢锁成功,pthread_cond_wait函数才会返回

7.3.3条件变量的唤醒

int pthread_cond_signal(pthread_cond_t *cond);int pthread_cond_broadcast(pthread_cond_t *cond);

pthread_cond_signal负责唤醒等待在条件变量上的一个线程。

pthread_cond_broadcast,就是广播唤醒等待在条件变量上的所有线程。

先发送信号,然后解锁互斥量,这个顺序是必须的嘛?

先通知条件变量、 后解锁互斥量, 效率会比先解锁、 后通知条件变量低。 因为先通知后解锁, 执行pthread_cond_wait的线程可能在互斥量已然处于加锁状态的时候醒来, 发现互斥量仍然没有解锁, 就会再次休眠, 从而导致了多余的上下文切换。

笨笨网美国主机,w ww.2 b p .n e t
提醒:《linux多线程服务器编程(全方面了解linux多线程服务)(9/13)》最后刷新时间 2025-03-21 11:13:52,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《linux多线程服务器编程(全方面了解linux多线程服务)(9/13)》该内容的真实性请自行鉴别。