Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1663446
  • 博文数量: 607
  • 博客积分: 10031
  • 博客等级: 上将
  • 技术积分: 6633
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-30 17:41
文章分类

全部博文(607)

文章存档

2011年(2)

2010年(15)

2009年(58)

2008年(172)

2007年(211)

2006年(149)

我的朋友

分类: LINUX

2007-11-29 11:58:15

by pascal4123

并发多线程之间必须协调好彼此的动作,避免一个线程的操作错误地影响其他线程而导致发生各种古怪问题.
这就是同步的起因.

原子指令
同步要求必须具有一种原子操作指令.可以排它性地执行测试和设置.
所有的同步操作都是基于这样一种原子指令的存在.

Critical Sections 临界区
必须保持数据完整性(原子性)的一段代码

所有的共享数据都必须加锁保护.否则会导致古怪的问题.
具体地,这些共享数据包括:全局变量,static变量,传给其他线程的数据,被多线程共享的数据结构等.

同步变量
POSIX实现了3种同步变量.
有2件事你想做:
1.你想保护共享数据,这个通过锁实现.
2.你想阻止线程空转浪费时间.这通过信号量,条件变量,join等做到

mutex 互斥锁
最简单.为代码段指定唯一的主人.第一个加锁的线程获得互斥锁的所有权,后续的线程试图加锁都会失败,并进入睡眠状态.当第一个线程解锁时,睡眠者之一将有机会获得锁,转为可运行状态Runnable
pthread_mutex_lock(m)
pthread_mutex_unlock(m)
互斥锁语句需要成对使用,有可能临界段发生异常导致无法正常解锁!构建异常安全的互斥锁的办法之一是将锁功能注入一个类,利用类的析构函数自动解锁.具体实现参见另外一篇文章: http://blog.chinaunix.net/u/16651/showart.php?id=248476

个别情况下,你想避免得锁不成进入睡眠的情况,可以使用pthread_mutex_trylock(),得锁成功返回0,否则返回EBUSY. 这个函数很少用到,用的话要谨慎.

semaphores 信号量
信号量对于串式的对象有用的.对于你想让线程等某件事情也是有用的.
信号量可以增加到任意大,但做多只能减小到零.信号量>0则操作成功.
P操作:sem_wait()
V操作:sem_post()

conditional variables 条件变量
条件变量提供了一种安全环境让线程测试条件.
线程获得锁后,测试条件:如果真,就执行,否则就释放锁并返回睡眠状态.直到另外1个线程改变了条件并唤醒它.然后你的线程重新获得锁,重新测试条件.
首先,别的线程唤醒你的线程之前可能没有完整地测试条件;
其次,就算唤醒之前条件真,等你被唤醒的线程准备开跑时条件可能变了;
第三,条件变量允许伪造的唤醒.

pthread_cond_signal()    唤醒某个睡眠的线程
pthread_cond_broadcast() 唤醒所有睡眠的线程

条件变量也允许你限制睡眠时间,到了一定时间就自动醒来
pthread_cond_timedwait()


可停止的生产者/消费者例子

void *producer(void *arg)
{
    request_t *request;
    while(1)
    {
        request = get_request();
        pthread_mutex_lock(&requests_lock);
        while ((length >= 10) && (!stop))
            pthread_cond_wait(&requests_producer, &requests_lock);
        add_request(request);
        length++;
        if (stop) break;
        pthread_mutex_unlock(&requests_lock);
        pthread_cond_signal(&requests_consumer);
    }
    pthread_mutex_unlock(&requests_lock);
    sem_post(&barrier);
    pthread_exit(NULL);
}

void *consumer(void *arg)
{
    request_t *request;
    while(1)
    {
        pthread_mutex_lock(&requests_lock);
        while ((length == 0) && (!stop))
            pthread_cond_wait(&requests_consumer, &requests_lock);
        if (stop) break;
        request = remove_request();
        length--;
        pthread_mutex_unlock(&requests_lock);
        pthread_cond_signal(&requests_producer);
        process_request(request);
    }
    pthread_mutex_unlock(&requests_lock);
    sem_post(&barrier);
    pthread_exit(NULL);
}

void *stopper(void *arg)
{
    sleep(4);
    pthread_mutex_lock(&requests_lock); /* REQUIRED! */
    stop = TRUE;
    pthread_mutex_unlock(&requests_lock);
    pthread_cond_broadcast(&requests_producer);
    pthread_cond_broadcast(&requests_consumer);
    pthread_exit(NULL);
}




阅读(1469) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~