网络编程系列之四 条件

条件是线程同步的另一种方法,下面是借鉴链接:

http://blog.chinaunix.net/uid-1849361-id-2825417.html

http://www.ibm.com/developerworks/cn/linux/thread/posix_thread3/index.html#icomments


基本概念和原理:

互斥对象是线程程序必需的工具,但它们并非万能的。例如,如果线程正在等待共享数据内某个条件出现,那会发生什么呢?代码可以反复对互斥对象锁定和解锁, 以检查值的任何变化。同时,还要快速将互斥对象解锁,以便其它线程能够进行任何必需的更改。这是一种非常可怕的方法,因为线程需要在合理的时间范围内频繁 地循环检测变化。
        在每次检查之间,可以让调用线程短暂地进入睡眠,比如睡眠三秒钟,但是因此线程代码就无法最快作出响应。真正需要的是这样一种方法,当线程在等待满足某些 条件时使线程进入睡眠状态。一旦条件满足,还需要一种方法以唤醒因等待满足特定条件而睡眠的线程。如果能够做到这一点,线程代码将是非常高效的,并且不会 占用宝贵的互斥对象锁。这正是 POSIX 条件变量能做的事!


使用过程:

首先需要锁定互斥对象,然后线程将调用 pthread_cond_wait(&mycond,&mymutex)。pthread_cond_wait() 调用相当复杂,pthread_cond_wait() 所做的第一件事就是同时对互斥对象解锁(于是其它线程可以进行加锁),并等待条件 mycond 发生(这样当 pthread_cond_wait() 接收到另一个线程的“信号”时,它将苏醒),现在互斥对象已被解锁。此时,pthread_cond_wait() 调用还未返回,因为它要对互斥对象进行加锁。 然后执行相关的操作。

关于mycond:

等待条件 mycond 通常是一个阻塞操作,这意味着线程将睡眠,在它苏醒之前不会消耗 CPU 周期。这正是我们期待发生的情况。线程将一直睡眠,直到特定条件发生,在这期间不会发生任何浪费 CPU 时间的繁忙查询。从线程的角度来看,它只是在等待 pthread_cond_wait() 调用返回。


整个过程是这样的:

1)本线程加锁

2)调用pthread_cond_wait 解锁,然后进入cpu的睡眠。

3)其他线程加锁并且修改了条件,然后解锁

4)本线程加锁,获得条件,pthread_cond_wait返回然后运行。

5)本线程解锁,整个过程完成。



//函数目的:第一个线程需要保证count的值为整数时对count自减,所以要等待其值为整数,这是对实际情况的模拟
//注意除了加锁和解锁,所有的函数要判断返回值是否正确
//用到的新函数如下:
//pthread_cond_init()
//pthread_cond_destroy()
//pthread_cond_signal()
//pthread_cond_broadcast()
//pthread_cond_wait()


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t  mymutex;
pthread_cond_t  mycond;
unsigned int count = 0;


void * first_thread (void *arg)
{
    pthread_mutex_lock(&mymutex);

    printf("1\n");
    if(pthread_cond_wait(&mycond,&mymutex) )
        printf("cond wait error\n");
    //这是等待条件满足后要执行的代码
    count--;
    printf("2\n");

    pthread_mutex_unlock(&mymutex);
    pthread_exit(NULL);
}

void * second_thread(void *arg)
{
    pthread_mutex_lock(&mymutex);

    printf("3\n");
    count++;

   // if(pthread_cond_signal(&mycond))
      // printf("signal error\n");      //唤醒第一个正在睡眠的线程
    if(pthread_cond_broadcast(&mycond))
        printf("broadcast error\n");   //唤醒所有正在睡眠的线程

    printf("4\n");

    pthread_mutex_unlock(&mymutex);
    pthread_exit(NULL);
}

int main()
{
    int res;    //查看返回值
    int hThread1,hThread2;   //创建两个线程

    //初始化锁和条件
    if(res = pthread_mutex_init(&mymutex,NULL)  )
        printf("mutex init error\n");

    if( res = pthread_cond_init(&mycond,NULL)  )
        printf("cond init error\n");

    if(res = pthread_create(&hThread1,NULL,first_thread,NULL))
        printf("create thread1 error\n");

    if(res = pthread_create(&hThread2,NULL,second_thread,NULL)  )
        printf("create thread2 error\n");


    if( pthread_join(hThread1,NULL) )
        printf("hThread1 join error\n");
    if( pthread_join(hThread2,NULL) )
        printf("hThread2 join error\n");

    //两个线程结束后释放锁和条件资源
    if(pthread_mutex_destroy(&mymutex))
        printf("mutex_destroy error\n");
    if(pthread_cond_destroy(&mycond))
        printf("cond_destroy error\n");

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值