网站排名优化教程,网站建设汇编材料,做游戏人设计网站,wordpress 自定义侧边栏http://blog.csdn.net/jnu_simba/article/details/9129939 一、posix 条件变量 一种线程间同步的情形#xff1a;线程A需要等某个条件成立才能继续往下执行#xff0c;现在这个条件不成立#xff0c;线程A就阻塞等待#xff0c;而线程B在执行过程中使这个条件成立了#x…http://blog.csdn.net/jnu_simba/article/details/9129939 一、posix 条件变量 一种线程间同步的情形线程A需要等某个条件成立才能继续往下执行现在这个条件不成立线程A就阻塞等待而线程B在执行过程中使这个条件成立了就唤醒线程A继续执行。 在pthread库中通过条件变量Condition Variable来阻塞等待一个条件或者唤醒等待这个条件的线程。Condition Variable用pthread_cond_t类型的变量表示和Mutex的初始化和销毁类似pthread_cond_init函数初始化一个Condition Variableattr参数为NULL则表示缺省属性pthread_cond_destroy函数销毁一个Condition Variable。如果ConditionVariable是静态分配的也可以用宏定义PTHEAD_COND_INITIALIZER初始化相当于用pthread_cond_init函数初始化并且attr参数为NULL。 一个Condition Variable总是和一个Mutex搭配使用的。一个线程可以调用pthread_cond_wait在一个Condition Variable上阻塞等待这个函数做以下三步操作 1. 释放Mutex 2. 阻塞等待 3. 当被唤醒时重新获得Mutex并返回 注意3个操作是原子性的操作之所以一开始要释放Mutex是因为需要让其他线程进入临界区去更改条件或者也有其他线程需要进入临界区等待条件。 一个线程可以调用 pthread_cond_signal 唤醒在某个Condition Variable上等待的第一个线程也可以调用 pthread_cond_broadcast 唤醒在这个Condition Variable上等待的所有线程。 上面的函数具体可以man 一下。 二、条件变量使用规范 一、等待条件代码 pthread_mutex_lock(mutex); while (条件为假 pthread_cond_wait(cond, mutex); 修改条件 pthread_mutex_unlock(mutex); 二、给条件发送通知代码 pthread_mutex_lock(mutex); 设置条件为真 pthread_cond_signal(cond); pthread_mutex_unlock(mutex); 假设第一段用于消费者线程第二段用于生产者线程。为什么消费者线程要用while 而不是if 就可以呢在man pthread_cond_wait 有一句If a signal is delivered to a thread waiting for a condition variable, upon return from the signal handler the thread resumes waiting for the condition variable as if it was not interrupted, or it shall return zero due to spurious wakeup. 即是说如果正在等待条件变量的一个线程收到一个信号从信号处理函数返回的时候线程应该重新等待条件变量就好象没有被中断一样或者被虚假地唤醒返回0。如果是上述情形那么其实条件并未被改变那么此时如果没有继续判断一下条件的真假就继续向下执行的话修改条件将会出现问题所以需要使用while 循环再判断一下如果条件还是为假必须继续等待。 注在多处理器系统中pthread_cond_signal 可能会唤醒多个等待条件的线程这也是一种spurious wakeup。 当生产者线程较多即生产得比较快在这边假设是无界的缓冲区比如链表可以不停地生产使用pthread_cond_signal 发出通知的时候如果此时没有消费者线程在等待条件那么这个通知将被丢弃但也不影响整体代码的执行没有消费者线程在等待说明产品资源充足即while 判断失败不会进入等待状态直接消费产品即修改条件。 三、生产者消费者问题 C Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 #include unistd.h #include sys/types.h #include pthread.h #include semaphore.h #include stdlib.h #include stdio.h #include errno.h #include string.h #define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0) #define CONSUMERS_COUNT 2 #define PRODUCERS_COUNT 1 pthread_mutex_t g_mutex; pthread_cond_t g_cond; pthread_t g_thread[CONSUMERS_COUNT PRODUCERS_COUNT]; int nready 0; void *consume(void *arg) { int num (int)arg; while (1) { pthread_mutex_lock(g_mutex); while (nready 0) { printf(%d begin wait a condtion ...\n, num); pthread_cond_wait(g_cond, g_mutex); } printf(%d end wait a condtion ...\n, num); printf(%d begin consume product ...\n, num); --nready; printf(%d end consume product ...\n, num); pthread_mutex_unlock(g_mutex); sleep(1); } return NULL; } void *produce(void *arg) { int num (int)arg; while (1) { pthread_mutex_lock(g_mutex); printf(%d begin produce product ...\n, num); nready; printf(%d end produce product ...\n, num); pthread_cond_signal(g_cond); printf(%d signal ...\n, num); pthread_mutex_unlock(g_mutex); sleep(1); } return NULL; } int main(void) { int i; pthread_mutex_init(g_mutex, NULL); pthread_cond_init(g_cond, NULL); for (i 0; i CONSUMERS_COUNT; i) pthread_create(g_thread[i], NULL, consume, (void *)i); sleep(1); for (i 0; i PRODUCERS_COUNT; i) pthread_create(g_thread[CONSUMERS_COUNT i], NULL, produce, (void *)i); for (i 0; i CONSUMERS_COUNT PRODUCERS_COUNT; i) pthread_join(g_thread[i], NULL); pthread_mutex_destroy(g_mutex); pthread_cond_destroy(g_cond); return 0; } 在上面程序中nready 就当作是生产产品了--nready就当作是消费产品了跟前面文章所不同的是这里没有缓冲区大小的概念可以当作是无界缓冲区生产者可以一直生产但消费者只有当有产品的时候才能消费否则就得等待等待结束的条件就是nready 0上面也说过当生产得比较快生产者线程多的时候也有可能消费者线程一直不存在等待的状态因为nready 的值很大即产品资源很多。现在设置的是2个消费者线程和1个生产者线程所以动态输出来看一般是2个消费者线程轮流等待。 参考 《linux c 编程一站式学习》 《UNP》