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

C++ 并行与分布式编程 chapter5 任务间并发的同步(1)

2010-11-19 19:38 447 查看
任务间并发的同步

同步任务之间的关系开始-开始关系(SS) 虚拟人(avatar)的嘴巴和声音同时执行

结束-开始关系(FS) 任务A不能结束直至任务B开始运行类似于父子进程,父进程产生一个子进程或者父进程从子进程接收到子进程已经开始运行的通信之前,父进程不能完全执行某些操作。

开始-结束关系(SF) 一个任务不能开始,直至另一个任务结束,在管道中读取数据

结束-结束关系(FF) 任务B结束之前,任务A不能结束。父进程必须等待子进程终止之后才能终止

同步数据的访问进程间共享数据的一种方法就是创建一个存储器块,然后将这个存储器块映射到需要共享该数据的进程的地址空间中;另一种方法就是在两个进程的地址空间外创建一个存储器块。IPC(Inter Process Communication)包括:管道、文件、和消息传递。在一个多线程环境中,必须对共享存储器、全局变量和文件的并发访问进行同步。临界区(Critical Section)是可以改变文件指针位置、写文件、关闭文件和读写全局变量或数据结构的任何代码块。

信号量信号量(semaphore)是管理同步关系和实现访问策略的一种同步机制。仅能被某些特定的操作访问。作为资源访问的关键字,这个关键字在某一时刻只能由一个进程或线程拥有。不管那个任务拥有该关键字,那么这个任务就对资源加锁,并独自使用这个资源。

P()是减少操作lock,V()增加操作unlock

 

P(Mutex)

 

if(Mutex > 0) {

  Mutex--;

}

else {

    Block on Mutex;

}

 

V(Mutex)

if(Blocked on Mutex N processes) {

  pass on Mutex;

}

else{

    Mutex++;

}

这两个操作的实现依赖于系统。信号量有几类:二进制信号量只有值0或1;计数信号量:一些非负的整数值。POSIX(Portable Operating System UNIX)定义了几种信号量。

1.互斥锁信号量 实现代码临界区互斥机制,通过串行化对临界区的访问来避免竞争的产生。基本操作

 

pthread_mutex_t Functions Mutex Operations

Function Prototypes/Macros #include <pthread.h>

Initialization

int pthread_mutex_init(pthread_mutex_t *restrict

mutex, const pthread_mutexattr_t *restrict attr);

 

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

Request ownership

<time.h>

 

int pthread_mutex_lock(pthread_mutex_t *mutex);

 

int pthread_mutex_timedlock(pthread_mutex_t

*restrict mutex, const struct tiemspec *restrict

abs_timeout);

Release ownership

int pthread_mutex_unlock(pthread_mutex_t *mutex);

Try ownership

int pthread_mutex_trylock(pthread_mutex_t *mutex);

Destruction

int pthread_mutex_destroy(pthread_mutex_t *mutex);

 

互斥锁有一个属性对象,传递给初始化函数,创建一个互斥锁,如果采用缺省属性可以使用宏pthread_mutext Mutex = PTHREAD_MUTEX_INITIALIZER;这种方法开销较小,但是不执行任何错误检查。

一个互斥锁可以是专有或共有的。请求所有权操作将互斥锁的所有权授予调用它的进程或线程。一旦互斥锁已经是专有的,那么线程或进程就可以对资源进行访问。如果其他进程或线程试图拥有互斥锁,这些进程或线程就会被阻塞,直到互斥锁可以利用。Try ownership用来测试一个互斥锁是否是专有的(owned),如果互斥锁是专有的,调用这个函数的进程或线程不会被阻塞,如果互斥锁是共有的(unowned),就授予该进程或线程专有权。如果存储器是专有或这有线程在等待这个互斥锁,那么存储器就不能被释放或者关闭(Destruction)。互斥锁实现EREW互斥读和互斥写

互斥锁属性对象的使用方法和线程属性对象的使用方法类似。封装互斥锁对象的所有属性。私有的互斥锁只能在相同的进程中的线程间共享;共享的互斥锁可以由对互斥锁所在存储器位置进行访问的任何线程使用,包括其他进程中的线程。

 

// ...

pthread_t ThreadA,ThreadB;

pthread_mutex_t Mutex;

pthread_mutexattr_t MutexAttr;

 

void *task1(void *X)

{

   pthread_mutex_lock(&Mutex);

   // critical section of code

   pthread_mutex_unlock(&Mutex);

   return(0);

}

 

void *task2(void *X)

{

   pthread_mutex_lock(&Mutex);

   // critical section of code

   pthread_mutex_unlock(&Mutex);

   return(0);

}

 

int main(void)

{

   //...

   pthread_mutexattr_init(&MutexAttr);

   pthread_mutex_init(&Mutex,&MutexAttr);

   //set mutex attributes

   pthread_create(&ThreadA,NULL,task1,NULL);

   pthread_create(&ThreadB,NULL,task2,NULL);

   //...

   return(0);

}

 

int Rt;

pthread_mutex_t Mutex1;

pthread_mutexattr_t MutexAttr;

 

 

 

int main(void)

{

   //...

   pthread_mutexattr_init(&MutexAttr);

   pthread_mutexattr_setpshared(&MutexAttr,

                                PTHREAD_PROCESS_SHARED);//初始化为共享

   pthread_mutex_init(&Mutex1,&MutexAttr);

 

   if((Rt = fork()) == 0){ // child process

      pthread_mutex_lock(&Mutex1);

      //critical section

      pthread_mutex_unlock(&Mutex1);

   }

   else{ // parent process

      pthread_mutex_lock(&Mutex1);

      //critical section

      pthread_mutex_unlock(&Mutex1);

   }

   //...

   return(0);

}

本文使用Blog_Backup未注册版本导出,请到soft.pt42.com注册。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: