第07章 互斥锁和条件变量

1.互斥锁的上锁与解锁

  • 基本用法

    见下文的例子

2.生产者与消费者模型

  • 这是一个经典的例子,不过同步是隐式的

    grep pattern chapters. *|wc -l

  • 第二次看发现一段话有点意思

      int dosignal;
      pthread_mutex_lock(&nready.mutex);
      dosignal = (nready.nready == 0);
      nready.nready++;
      pthread_mutex_unlock(&nready.mutex);
    
      if(dosignal)
          pthread_cond_signal(&nready.cond);
    

    注意这里先释放的互斥锁才发送信号。书上说Posix明确允许这么做:调用pthread_cond_signal的线程不必是与之关联的互斥锁的当前属主。不过Posix接着说:如果需要可预见的调度行为,那么调用pthread_cond_signal的线程必须锁住该互斥锁

    • 允许这么做但是又有不可预期的调度行为??那究竟该不该这么做呢??

3.定时等待与广播

  • 下面是我写的一个测试代码
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <time.h>

//静态的可以用宏初始化
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

struct timespec g_waitTime;

void set_time(struct timespec *outtime,int ms,int ns);
void *produce(void *), *consume(void *);

int main(int argc,char *argv[])
{
    int i=0;
    pthread_t	tid_produce[5], tid_consume;

    set_time(&g_waitTime,2,2);
    for (i = 0; i < 5; i++) {
		pthread_create(&tid_produce[i], NULL, produce, NULL);
	}
    pthread_create(&tid_consume, NULL, consume, NULL);

    for (i = 0; i < 5; i++) {
		pthread_join(tid_produce[i], NULL);
	}
    pthread_join(tid_consume, NULL);
    pthread_mutex_destroy(&lock);
    pthread_cond_destroy(&cond);
    return 0;
}

void *produce(void *arg)
{
    pthread_mutex_lock(&lock);
    //pthread_cond_wait(&cond,&lock);
    if(pthread_cond_timedwait(&cond,&lock,&g_waitTime) == ETIMEDOUT)
        printf("ETIMEDOUT\n");
    else
        printf("wake up\n");
    pthread_mutex_unlock(&lock);
    return NULL;
}


void *consume(void *arg)
{
    pthread_mutex_lock(&lock);
    //pthread_cond_signal(&nready.cond);
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&lock);
    return NULL;
}
void set_time(struct timespec *outtime,int ms,int ns)
{
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    outtime->tv_sec = ts.tv_sec +ms;
    outtime->tv_nsec = ts.tv_nsec + ns;
}

4.互斥锁与条件变量的属性

  • 以下代码片段给出初始化一个互斥锁以便它能在进程间共享的过程

    注:不销毁可能应发内存泄漏
    进程间共享互斥锁时,进程在持锁期间可能终止(没有办法让系统自动释放)

pthread_mutex_t *mptr; /*放到共享内存*/
pthread_mutexattr mattr;
...
mptr = /*some value that point to shared memory*/
pthread_mutexattr_init(&mattr);
#ifdef _POSIX_THREAD_PROCESS_SHARED
    pthread_mutexattr_setpshared(&mattr,PTHREAD_PROCESS_SHARED);
#else
#error this implementation does not support _POSIX_THREAD_PROCESS_SHARED
#endif
    pthread_mutex_init(mptr,&mattr);
    pthread_mutex_destroy(&mptr);
    pthread_cond_destroy(&mattr);
;