linux高级编程(四、线程互斥与同步).doc_第1页
linux高级编程(四、线程互斥与同步).doc_第2页
linux高级编程(四、线程互斥与同步).doc_第3页
linux高级编程(四、线程互斥与同步).doc_第4页
linux高级编程(四、线程互斥与同步).doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

/ 第四天 线程同步 / 多线程同步问题 线程共享进程的资源和地址空间 任何线程对系统资源的操作都会给其他线程带来影响 线程共享进程的资源和地址空间,对这些资源进行操作时,必须考虑线程间同步与互斥问题三种线程同步机制互斥锁信号量条件变量互斥锁用简单的加锁方法控制对共享资源的原子操作只有两种状态: 上锁、解锁 互斥锁:更适合同时可用的资源是惟一的情况可把互斥锁看作某种意义上的全局变量在同一时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程能够对共享资源进行操作若其他线程希望上锁一个已经被上锁的互斥锁,则该线程就会挂起,直到上锁的线程释放掉互斥锁为止互斥锁保证让每个线程对共享资源按顺序进行原子操作互斥锁分类区别在于其他未占有互斥锁的线程在希望得到互斥锁时是否需要阻塞等待快速互斥锁?调用线程会阻塞直至拥有互斥锁的线程解锁为止?默认为快速互斥锁检错互斥锁?为快速互斥锁的非阻塞版本,它会立即返回并返回一个错误信息 互斥锁主要包括下面的基本函数:互斥锁初始化:pthread_mutex_init()互斥锁上锁:pthread_mutex_lock()互斥锁判断上锁:pthread_mutex_trylock()互斥锁解锁:pthread_mutex_unlock()消除互斥锁:pthread_mutex_destroy() 3.线程的互斥 作用是用于互斥(即运行当前的不能运行另一个) 实现线程间同时访问共享的资源,避免同时操作 pthread_mutex_t /互斥量(锁)类型,用来定义互斥量 对互斥量做初始化 int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); restrict mutex:互斥量的地址,互斥量通过这个函数获取初始值 restrict attr: 属性,通常为NULL 互斥锁与解锁 int pthread_mutex_lock(pthread_mutex_t *mutex); /加锁, int pthread_mutex_unlock(pthread_mutex_t *mutex);/解锁 mutex:为互斥量的地址 例: pthread_mutex_t mutex;/定义互斥量 char buf1024; void *thr_fn1(void *arg) int i=0; while(1) pthread_mutex_lock(&mutex); sprintf(buf,thr_fn1 -%dn,i+); printf(%sn,buf); sleep(8); pthread_mutex_unlock(&mutex); usleep(50000); return (void*)23;/用return跳出线程 void *thr_fn2(void *arg) int i=0; while(1) pthread_mutex_lock(&mutex); sprintf(buf,thr_fn2 -%dn,i+); printf(%sn,buf); pthread_mutex_unlock(&mutex); usleep(50000); pthread_exit(void*)24); int main(int argc,char *argv) pthread_mutex_init(&mutex,NULL); void *tret; pthread_t tid1,tid2,tid3; pthread_create(&tid1,NULL,thr_fn1,NULL); pthread_create(&tid2,NULL,thr_fn2,NULL); pthread_join(tid2,&tret); pthread_join(tid1,&tret); return 0; 4.线程的同步(条件变量) 同步:就是线程待某件事件的发生,当等待事件发生时,被等待的线程和事件一起继续执行 待待的线程在事件未发生时则挂起。 pthread_cond_t 是线程同的的条件变量 1)对变量进行初始化 int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); restrict cond:条件变量 restrict attr:属性,通常设为NULL 2)线程同步等待函数 int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); cond:线程同步的条件变量 mutex:线程互斥量 作用:是等待条件的发生,被调用后线程自动阻塞,直到相应的条件被设置。在等待时,不占用CPU时间 在等待的同时直接解锁,在接到信号后马上加锁 3)发送条件信号的函数 int pthread_cond_signal(pthread_cond_t *cond); cond:线程同步的条件 例:在某种情况下,激活另一个线程 pthread_mutex_t mutex;/定义互斥量 pthread_cond_t cond; /定义同步条件 int count; void *thr_fn1(void *arg) while(1) pthread_mutex_lock(&mutex); if (count 5) pthread_cond_wait(&cond,&mutex); count-; printf(- %dn,count); pthread_mutex_unlock(&mutex); usleep(50); void *thr_fn2(void *arg) while(1) pthread_mutex_lock(&mutex); if (count =10) pthread_cond_signal(&cond); count+; printf(2- %dn,count); pthread_mutex_unlock(&mutex); sleep(1); /注意:在解锁后一定用sleep给另一线程获取CPU的机会 int main(int argc,char *argv) pthread_mutex_init(&mutex,NULL); pthread_cond_init(&cond,NULL); void *tret; pthread_t tid1,tid2,tid3; pthread_create(&tid1,NULL,thr_fn1,NULL); pthread_create(&tid2,NULL,thr_fn2,NULL); pthread_join(tid2,&tret); pthread_join(tid1,&tret); return 0; /-下午- 线程同步(信号量) 信号量 本质上是一个整数计数器,被用来控制对公共资源的访问 信号量:更适合同时可用的资源为多个的情况 操作系统中所用到的PV原子操作,广泛用于进程或线程间的同步与互斥 PV操作,P是通过的意思,V是释放的意思。是指不可中断的过程,由操作系统来保证P操作和V操作 PV操作的前题假定存整型变量sem PV操作的过程就是对该变量值进行加减的过程 P操作过程 sem减1,若sem仍大于0,则p操作返回,该进程继续执行,若小于0,则该进程被阻塞 V操作过程 sem加1 若sem大于0,则V操作返回,进程继续执行,若小于0,则唤醒一个该信号量上的进程 在 Linux 中,可以使用 sem_init()来创建一个无名的 POSIX 信号量 semget() 用于创建 System V 信号量信号量函数 #include 用sem_t类型来声明一个型号量。 1.初始化信号量 int sem_init(sem_t *sem, int pshared, unsigned int value) sem 信号量 pshared 共享方式 ,表示这个信号量只是当前进程中的型号量, 如果不为,这个信号量可能可以在两个进程中共享。 value 信号量初始值 2.P操作,减少信号量 sem_wait(sem_t *sem) sem_trywait(sem_t *sem); 函数用于接受信号,当sem0时就能接受到信号,然后将sem-; 两个函数都是在信号量大于零时将信号量的值减一区别: 若信号量小于零时,sem_wait()将会阻塞线程,sem_trywait()则会立即返回 3.V操作,增加信号量 sem_post(sem_t *sem) 将信号量的值加一同时发出信号来唤醒等待的线程 4.解除信号量 sem_destroy(sem_t *sem) 函数用于解除信号量。 5.获取信号量的值 sem_getvalue(set_t *sem)例: #include #include #include sem_t sem1, sem2; void *thread1(void *arg) sem_wait(&sem1); printf(hello n); sem_post(&sem2); void *thread2(void *arg) sem_wait(&sem2); printf(world!n); int main() pthread_t t1, t2; sem_init(&sem1,0,1); sem_init(&sem2,0,0); pthread_create(&t1,NULL,thread1,NULL); pthread_create(&t2,NULL,thread2,NULL); pthread_join(t1,NULL); pthread_join(t2,NULL); sem_destroy(&sem1); sem_destroy(&sem2); return 0; 在多进程编程中,进程A需要暂时阻塞,等待另一进程B访问资源,当B处理结束后,进程A再继续执行。这种情况下用到进程同步。 信号量实现的是一种类似计数器的功能,用来实现进程间的互斥及同步 信号量的数据结构: struct semid_ds struct ipc-perm sem_perm; /许可权限 time_t sem_otime; /最后一次操作时间 time_t sem_ctime; /最后一次调用semctl时间 unsigned long sem_nsems; /信号量个数 ; PV操作主要用于线程间的同步和互斥互斥,几个线程只设置一个信号量sem同步,会设置多个信号量,安排不同初值来实现它们之间的顺序执行 - 信号量sem =0 | / | sem0 | P操作/ V操作 | sem -1 sem+1 | | | | 进程阻塞|- 阻塞进程队列- 唤醒进程当信号量sem的值大于等于零时,该进程(或线程)具有公共资源的访问权限当信号量sem的值小于零时,该进程(或线程)就将阻塞直到信号量sem的值大于等于0为止 PV 操作在进程间通信过程中,用来实现进程对资源的互斥访问,实现进程间的同步 例: #include #include #include #include #define THREAD_NUM 3 #define REPEAT_TIMES 5 #define DELAY 4 sem_t semTHREAD_NUM; void *thrd_func(void *arg) int thrd_num=(void*)arg; / 参数no int delay_time,count; / 带有阻塞的p操作 sem_wait(&semthrd_num); printf(Thread %d is starting.n,thrd_num); for(count=0;countREPEAT_TIMES;count+) printf(/-n); sleep(delay_time); printf(Thread %d is exiting.n,thrd_num); / 对前一个信号量进行V操作 / 由于只有最后一个信号量初始化为1,其余均为0 / 故线程执行的顺序将为逆序 sem_post(&sem(thrd_num+THREAD_NUM-1)%THREAD_NUM); pthread_exit(NULL); / 线程主动结束 int main() pthread_t threadTHREAD_NUM; int no; void *tret; srand(int)time(0); / 初始化THREAD_NUM-1个信号量,均初始化为0 for(no=0;noTHREAD_NUM-1;no+) sem_init(&semno,0,0); / sem2信号量初始化为1,即sem数组中最后一个信号量 sem_init(&sem2,0,1); / 创建THREAD_NUM个线程,入口函数均为thrd_func,参数为(void*)no for(no=0;noTHREAD_NUM;no+) if (pthread_create(&threadno,NULL,thrd_func,(void*)no)!=0) printf(Create thread %d error!n,no); ex

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论