您的位置:首页 > 编程语言

POSIX thread编程中关于临界区内条件变量的分析

2012-10-30 14:47 337 查看
0x00 前言

  由于前几天想做一个工具,要用到perl的多线程,由此而联想到posix C中关于条件变量的一些想法,为了证明自己的想法是对的,特地做了一次实验,从而实现对POSIX PTHREAD的一些实现的猜想证实

0x01 理论

  a. linux中的进程与子进程之间共享父进程的资源,进程有自己的堆栈空间,虽然子进程在创建时间只是拷贝了父进程的PID、必须的资源等一些基本信息,但后续需要可以进行读/写时拷贝,而线程是只占有生成线程的进程中的部分栈空间,故线程没有自己的资源

b. 竞争的前提是资源共享

  c. 解决竞争的实质是把共享的资源放进临界区,或者划分成不共享,即实现CPU处理的时分空间并行叠加

  d. 互斥锁机制是针对单一资源共享形成的临界区,但是等待锁的线程在等待时间是消耗CPU的,互斥锁嵌套时间按照操作顺序可对多个共享资源加锁,从而避免死锁

  e. 条件变量加互斥锁是解决多资源共享并且资源间操作有顺序性时间提高CPU利用率的方式,因为在进入条件变量的临界区后,条件不满足就会解锁并让出CPU让其他线程执行,等待条件满足后,发信号给等待线程进行处理

  f. 信号量解决多资源并行处理临界区的方式,强调资源的并行与有无,即是P、V操作

0x02 实践分析

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

#define FOR_END 10

int             index;
pthread_mutex_t mutex;
pthread_cond_t  cond_t;

void *thread_func_one(void *args);
void *thread_func_two(void *args);

int main(int argc, char *argv[])
{
pthread_t pt_one;
pthread_t pt_two;
int       pid_one;
int       pid_two;

pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond_t, NULL);

pid_one = pthread_create(&pt_one, NULL, thread_func_one, NULL);
if(pid_one)
{
printf("thread one create failt!\n");
return -1;
}

pid_two = pthread_create(&pt_two, NULL, thread_func_two, NULL);
if(pid_two)
{
printf("thread two create failt!\n");
return -1;
}

pthread_join(pt_one, NULL);
pthread_join(pt_two, NULL);

pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond_t);

return 0;
}

void *thread_func_one(void *args)
{
for(index = 0; index < FOR_END; index++)
{
pthread_mutex_lock(&mutex);
if(!(index % 2))
{
printf("pthread one signal before\n");
pthread_cond_signal(&cond_t);
printf("pthread one signal\n");
}
printf("pthread one print %d\n", index);
pthread_mutex_unlock(&mutex);
sleep(1);
}
pthread_cond_signal(&cond_t);
index = -1;
}

void *thread_func_two(void *args)
{
while(1)
{
pthread_mutex_lock(&mutex);
if(index == -1)
{
break;
}

if(index % 2)
{
printf("pthread two wait before\n");
pthread_cond_wait(&cond_t, &mutex);
printf("pthread two wait\n");
}

printf("pthread two print %d\n", index);
pthread_mutex_unlock(&mutex);

sleep(1);
}
}


程序输出结果:

pthread one signal before
pthread one signal
pthread one print 0
pthread two print 0
pthread one print 1
pthread two wait before //阻塞了
pthread one signal before //这个时候还能运行说明全局变量被现在加锁了,也就是被阻塞的thread2释放了锁
pthread one signal
pthread one print 2
pthread two wait //解开前面的阻塞了
pthread two print 2
pthread one print 3
pthread two wait before
pthread one signal before
pthread one signal
pthread one print 4
pthread two wait
pthread two print 4
pthread one print 5
pthread two wait before
pthread one signal before
pthread one signal
pthread one print 6
pthread two wait
pthread two print 6
pthread one print 7
pthread two wait before
pthread one signal before
pthread one signal
pthread one print 8
pthread two wait
pthread two print 8
pthread one print 9
pthread two wait before
pthread two wait
pthread two print -1


0x03 结尾

以上程序说明了:

a. pthread_cond_wait:函数阻塞当前线程释放锁并释放CPU时间片,等待收到信号后并获得CPU时间片后继续运行

b. phtread_cond_signal: 发送信号唤醒wait线程,每次只能唤醒一个
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: