#include<pthread.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
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);
}
ide
}this
*********************************************************************spa
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;
}rest
示例的解釋:
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進行解鎖。
隊列
.......進程