linux条件变量cond,Linux 条件变量 pthread_cond_signal及pthread_cond_wait
#include
#include
#include
#include
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*靜態初始化*/
pthread_cond_t? cond = PTHREAD_COND_INITIALIZER;? //init cond
void *thread1(void*);
void *thread2(void*);
int i = 1; //global
int main(int argc,char*? argv[])
{
pthread_t t_a;
pthread_t t_b;//two thread
pthread_create(&t_b,NULL,thread2,(void*)NULL);//Create thread
pthread_create(&t_a,NULL,thread1,(void*)NULL);
pthread_join(t_b,NULL);//wait a_b thread end
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
exit(0);
}
//t_a? 實現線程t_b打印9以內3的倍數
void *thread1(void *junk){
for(i = 1;i<= 9; i++){
pthread_mutex_lock(&mutex); //互斥鎖
printf("call thread1 \n");
if(i%3 == 0)
pthread_cond_signal(&cond); //send sianal to t_b
else
printf("thread1: %d\n",i);
pthread_mutex_unlock(&mutex);
printf("1? [%d]\n",i);
sleep(1);
}
}
//t-b? 打印其他的數
void *thread2(void*junk){
while(i < 9)
{
pthread_mutex_lock(&mutex);//開始進入臨界區
printf("call thread2 \n");
if(i%3 != 0)//操作有2步,是原子操作。第一解鎖,先解除之前的pthread_mutex_lock鎖定的mutex;第二 掛起,阻塞并在等待隊列里休眠,即所在線程掛起,直到再次被再次喚醒,喚醒的條件是由pthread_cond_signal(&cond);發出的cond信號來喚醒。
pthread_cond_wait(&cond,&mutex); //wait 必須和互斥鎖同時用在一個線程里,它同時起到對資源的加鎖和解鎖
printf("thread2: %d\n",i);
pthread_mutex_unlock(&mutex);//離開臨界區
printf("2 ....\n"? );
sleep(1);
}
}
*********************************************************************
int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
pthread_cond_wait 源碼
{
volatile pthread_descr self = thread_self();
pthread_extricate_if extr;
int already_canceled = 0;
int spurious_wakeup_count;
/* Check whether the mutex is locked and owned by this thread.? */
if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP
&& mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP
&& mutex->__m_owner != self)
return EINVAL;
/* Set up extrication interface */
extr.pu_object = cond;
extr.pu_extricate_func = cond_extricate_func;
/* Register extrication interface */
THREAD_SETMEM(self, p_condvar_avail, 0);
__pthread_set_own_extricate_if(self, &extr);
/* Atomically enqueue thread for waiting, but only if it is not
canceled. If the thread is canceled, then it will fall through the
suspend call below, and then call pthread_exit without
having to worry about whether it is still on the condition variable queue.
This depends on pthread_cancel setting p_canceled before calling the
extricate function. */
__pthread_lock(&cond->__c_lock, self);
if (!(THREAD_GETMEM(self, p_canceled)
&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
enqueue(&cond->__c_waiting, self);
else
already_canceled = 1;
__pthread_unlock(&cond->__c_lock);
if (already_canceled) {
__pthread_set_own_extricate_if(self, 0);
__pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
pthread_mutex_unlock(mutex);
spurious_wakeup_count = 0;
while (1)
{
suspend(self);
if (THREAD_GETMEM(self, p_condvar_avail) == 0
&& (THREAD_GETMEM(self, p_woken_by_cancel) == 0
|| THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
{
/* Count resumes that don't belong to us. */
spurious_wakeup_count++;
continue;
}
break;
}
__pthread_set_own_extricate_if(self, 0);
/* Check for cancellation again, to provide correct cancellation
point behavior */
if (THREAD_GETMEM(self, p_woken_by_cancel)
&& THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
THREAD_SETMEM(self, p_woken_by_cancel, 0);
pthread_mutex_lock(mutex);
__pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
}
/* Put back any resumes we caught that don't belong to us. */
while (spurious_wakeup_count--)
restart(self);
pthread_mutex_lock(mutex);
return 0;
}
示例的解釋:
call thread2:是線程2即t_b首先上鎖,即 pthread_mutex_lock(&mutex);鎖住了mutex使得此進程執行線程2中的臨界區的代碼,當執行到45行:if(i%3 != 0),此時i=1,滿足此條件,則執行46行: pthread_cond_wait(&cond,&mutex); 這句是關鍵,pthread_cond_wait(&cond,&mutex)操作有兩步,是原子操作:第一 解鎖,先解除之前的pthread_mutex_lock鎖定的mutex;第二 掛起,阻塞并在等待對列里休眠,即線程2掛起,直到再次被喚醒,喚醒的條件是由pthread_cond_signal(&cond);發出的cond信號來喚醒。
call thread1:由于pthread_cond_wait已經對線程2解鎖,此時另外的線程只有線程1,那么線程1對mutex上鎖,若這時有多個線程,那么線程間上鎖的順序和操作系統有關。
thread1: 1:線程1上鎖后執行臨界區的代碼,當執行到if(i%3 == 0)此時i=1,不滿足條件,則pthread_cond_signal(&cond);不被執行,那么線程2仍處于掛起狀態,輸出thread1: 1后線程1由pthread_mutex_unlock(&mutex);解鎖。
thread1: 2:這時此進程中只有2個線程,線程2處于掛起狀態,那么只有線程1,則線程1又對mutex上鎖,此時同樣執行臨界區的代碼,而且i=2,不滿足條件,pthread_cond_signal(&cond);不被執行,那么線程2仍處于掛起狀態,輸出thread1: 1后線程1由pthread_mutex_unlock(&mutex);解鎖。
call thread1:同樣由線程1上鎖,但此時i=3,滿足條件pthread_cond_signal(&cond)被執行,那么pthread_cond_signal(&cond)會發出信號,來喚醒處于掛起的線程2。
thread2: 3:由于pthread_cond_signal喚醒了線程2,即i=3滿足條件,pthread_cond_wait(&cond,&mutex);被執行,那么pthread_cond_wait(&cond,&mutex)此時也有一步操作:上鎖;即對線程2上鎖,此時的pthread_cond_wait(&cond,&mutex)的操作相當與pthread_mutex_lock(&mutex);那么線程2繼續執行上鎖后的臨界區的代碼,并由pthread_mutex_unlock(&mutex);對線程2進行解鎖。
.......
總結
以上是生活随笔為你收集整理的linux条件变量cond,Linux 条件变量 pthread_cond_signal及pthread_cond_wait的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机数值方法(1):引论
- 下一篇: VTK:图像平滑——中值滤波器