from:http://stackoverflow.com/questions/1640389/pthreads-pthread-cond-signal-from-within-critical-section
Question1:
I have the following piece of code in thread A, which blocks using pthread_cond_wait()
pthread_mutex_lock(&my_lock);
if ( false == testCondition )
pthread_cond_wait(&my_wait,&my_lock);
pthread_mutex_unlock(&my_lock);
pthread_mutex_lock(&my_lock);
testCondition = true;
pthread_cond_signal(&my_wait);
pthread_mutex_unlock(&my_lock);
pthread_mutex_lock(&my_lock);
testCondition = true;
pthread_mutex_unlock(&my_lock);
pthread_cond_signal(&my_wait);
pthread_mutex_lock(&my_lock);
while ( false == testCondition ) {
pthread_cond_wait(&my_wait,&my_lock);
}
pthread_mutex_unlock(&my_lock);
(I also corrected what was probably a typo in your original example, which is the use of my_mutex for the pthread_cond_wait() call instead of my_lock.)
Question2:
为了判断所有线程已经终止而又不用pthread_join,只好又引入另外一个pthread同步对象:条件变量.
/* current working threads number */
static int curnum = 0;
/* mutex lock for curnum */
static pthread_mutex_t mutex_curnum = PTHREAD_MUTEX_INITIALIZER;
/* cond for curnum */
static pthread_cond_t cond_curnum = PTHREAD_COND_INITIALIZER;
变量curnum代表当前活动线程数,在线程scan函数结尾增加一下代码:
pthread_mutex_lock(&mutex_curnum);
if (!--curnum)
pthread_cond_signal(&cond_curnum);
pthread_mutex_unlock(&mutex_curnum);
return NULL;
每个线程终止时把curnum减1,如果curnum等0,那么通知main所有线程都已
终止. main在创建完线程后就已以下代码阻塞在cond_curnum上:
pthread_mutex_lock(&mutex_curnum);
while(curnum)
pthread_cond_wait(&cond_curnum,&mutex_curnum);
pthread_mutex_unlock(&mutex_curnum);
********************************************
pthread_cond_signal 一定要放在pthread_mutex_unlock之前吗?
Answer2:
"pthread_cond_signal()必须要放在pthread_mutex_lock() 和pthread_mutex_unlock() 之间, " 这个做法有个问题,举个例子 简单假设线程1、2,curnum 值为 1, 语句执行顺序如下: |
T2-->;pthread_mutex_lock(&mutex_curnum);
T2-->;while(curnum)
T2-->; pthread_cond_wait(&cond_curnum,&mutex_curnum);/*T2解锁,睡眠,等信号*/
T1-->;pthread_mutex_lock(&mutex_curnum); /*轮T1运行,T1上锁*/
T1-->;if (!--curnum) /*条件成立*/
T1-->; pthread_cond_signal(&cond_curnum); /*T1向线程T2发信号*/
T2-->;pthread_cond_wait(&cond_curnum,&mutex_curnum); /*T1时间片用完,换T2执行,但发觉不能上锁,因为T1持有锁*/
T1-->;pthread_mutex_unlock(&mutex_curnum); /*T1解锁*/
pthread_mutex_lock();
判断是否别个线程等待的条件发生,是的话设 "发生标志" 为 "是";
pthread_mutex_unlock();
if (发生标志 == 是)
{
pthread_cond_signal(...);
}
例子如下:
shows an example of how to use condition variables and mutexes together to synchronize threads.
The condition is the state of the work queue. We protect the condition with a mutex and evaluate the condition in a while loop. When we put a message on the work queue, we need to hold the mutex, but we don't need to hold the mutex when we signal the waiting threads. As long as it is okay for a thread to pull the message off the queue before we call cond_signal, we can do this after releasing the mutex. Since we check the condition in a while loop, this doesn't present a problem: a thread will wake up, find that the queue is still empty, and go back to waiting again. If the code couldn't tolerate this race, we would need to hold the mutex when we signal the threads.
gure 11.14. Using condition variables#includestruct msg { struct msg *m_next; /* ... more stuff here ... */ }; struct msg *workq; pthread_cond_t qready = PTHREAD_COND_INITIALIZER; pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER; void process_msg(void) { struct msg *mp; for (;;) { pthread_mutex_lock(&qlock); while (workq == NULL) pthread_cond_wait(&qready, &qlock); mp = workq; workq = mp->m_next; pthread_mutex_unlock(&qlock); /* now process the message mp */ } } void enqueue_msg(struct msg *mp) { pthread_mutex_lock(&qlock); mp->m_next = workq; workq = mp; pthread_mutex_unlock(&qlock); pthread_cond_signal(&qready); }