APUE之线程(五)
来源:互联网 发布:怎么做淘宝客服怎么找 编辑:程序博客网 时间:2024/04/18 03:47
线程同步:
读写锁:
继续往下说线程同步问题。读写锁与互斥量类似,但是读写锁的好处是允许更高的并行性。读写锁有三种状态:读模式下加锁状态,写模式下加锁状态,不加锁状态。下面有中情况需要说明以下,写加锁状态时,未被解锁的时候,所有试图对这个锁进行加锁的线程都会被阻塞。读加锁状态时,所有以读模式对它进行加锁的线程都可以得到访问的权限,但是如果线程希望以写模式对此锁进行加锁时,必须阻塞到所有线程释放读锁。读写锁比较适合与对于数据结构读的次数远远大于写的情况。
与互斥量一样,读写锁在使用的时候也需要初始化,在释放他们底层的内存前必须销毁。
#include <pthread.h>int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);int pthread_rwlock_destory(pthread_rwlock_t *rwlock);pthread_rwlock_init()进行初始化,释放读写锁占用的内存前,用pthread_rwlock_destory()做清理工作。
下面就是三种锁的函数:
#include <pthread.h>int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);<span style="white-space:pre"></span>//读锁int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);<span style="white-space:pre"></span>//写锁int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);<span style="white-space:pre"></span>//解锁补充一下有条件的读写锁原语:
#include <pthread.h>int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);下面的程序是使用读写锁的一个例子:
/* *Name : list11_8.c *Author : Lniper *Date : 2016-02-17 *Aim : Using the write and read lock. */#include <stdlib.h>#include <pthread.h>struct job{struct job *j_next;struct job *j_prev;pthread_t j_id;/* tells which thread handles this job *//* ... more stuff here ... */};struct queue{struct job *q_head;struct job *q_tail;pthread_rwlock_t q_lock;};/* *Initialize a queue. */int queue_init(struct queue *qp){int err;qp->q_head = NULL;qp->q_tail = NULL;err = pthread_rwlock_init(&qp->q_lock, NULL);if(err != 0)return (err);/* ... continue initialization ... */return(0);}/* *Insert a job at the head of the queue. */void job_insert(struct queue *qp, struct job *jp){pthread_rwlock_wrlock(&qp->q_lock);jp->j_next = qp->q_head;jp->j_prev = NULL;if(qp->q_head != NULL)qp->q_head->j_prev = jp;else qp->q_tail = jp;/* list was empty */qp->q_head = jp;pthread_rwlock_unlock(&qp->q_lock);}/* *Append a job on the tail of the queue. */void job_append(struct queue *qp, struct job *jp){pthread_rwlock_wrlock(&qp->q_lock);jp->j_next = NULL;jp->j_prev = qp->q_tail;if(qp->q_tail != NULL)qp->q_tail->j_next = jp;else qp->q_head = jp;/* list was empty */qp->q_tail = jp;pthread_rwlock_unlock(&qp->q_lock);}/* *Remove the given job from a queue. */void job_remove(struct queue *qp, struct job *jp){pthread_rwlock_wrlock(&qp->q_lock);if (jp == qp->q_head) {qp->q_head = jp->j_next;if(qp->q_tail == jp)qp->q_tail = NULL;} else if (jp == qp->q_tail) {qp->q_tail = jp->j_prev;if(qp->q_head == jp)qp->q_head = NULL;} else {jp->j_prev->j_next = jp->j_next;jp->j_next->j_prev = jp->j_prev;}pthread_rwlock_unlock(&qp->q_lock);}/* *Find a job for the given thread ID. */struct job *job_find(struct queue *qp, pthread_t id){struct job *qp;if(pthread_rwlock_rdlock(&qp->q_lock) != 0)return (NULL);for(jp = qp->q_head; jp != NULL; jp = jp->j_next)if(pthread_equal(jp->j_id, id))break;pthread_rwlock_unlock(&qp->q_lock);return (jp);}这个例子中,无论什么时候需要增加一个作业到队列中或者从队列中删除作业,都用写模式锁住队列的读写锁。另外无论什么时候搜索队列,首先需要获取读模式下的锁,允许所有的工作线程并发的搜索队列。这种情况下如果想改善性能,只有线程搜索队列的频率远远高于增加或者删除作业的频率。
条件变量:
这个是线程可用的另一种同步机制。条件变量给多个线程提供了一个会合的场所。条件变量和互斥量一起使用的时候,允许线程以无竞争的方式等待特定的条件发生。
#include <pthread.h>int pthread_cond_init(pthread_cond_t *restrict cond, pthread_condattr_t *restrict attr);int pthread_cond_destroy(pthread_cond_t *cond);pthread_cond_init()函数是动态分配的初始化函数,PTHREAD_COND_INITIALIZER分给静态分配的条件变量。pthread_cond_destroy()函数对条件变量进行去除初始化。
#include <pthread.h>int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict timeout);pthread_cond_timedwait()函数提供了timeout,timeout指定了等待的时间,通过timespec结构指定。时间用秒数或者分秒数来表示(纳秒)。
struct timespec {time_ttv_sec;/* seconds */longtv_nsec;/* nanoseconds */};下面提供两个函数对于唤醒等待条件的某个或者所有的线程:
#include <pthread.h>int pthread_cond_signal(pthread_cond_t *cond);<span style="white-space:pre"></span>//唤醒等待该条件的某个线程int pthread_cond_broadcast(pthread_cond_t *cond);<span style="white-space:pre"></span>//唤醒等待该条件的所有线程
下面的代码是结合条件变量和互斥量对线程进行同步。
/* *Name : list11_9.c *Author : Lniper *Date : 2016-02-17 *Aim : The condition variable and mutex make the thread synchronization. */#include <pthread.h>struct msg{struct msg *m_next;/* ... more stuff here ... */};structy msg *workq;pthread_cond_t qready = PTHREAD_COND_INITIALIZER;pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;void process_msg(void){struct msg *mp;for (;;) {pthread_mutex_lock(&qlock);while (workq = NULL)pthread_cond_wait(&qready, &qlock);mp = workq;workq = mp->m_next;pthread_mutex_unlock(&qlock);/* new process the message mp */}}void enqueue_msg(struct msg *mp){pthread_mutex_lock(&qlock);mp->m_next = workq;workq = mp;pthread_mutex_unlock(&qlock);pthread_cond_signal(&qready);}
总结:
对于线程的同步的三种基本的机制:互斥,读写锁以及条件变量。对于线程的同步还需要多多的实践,编写程序才能更好的理解线程同步的精髓。 0 0
- APUE之线程(五)
- APUE之线程(二)
- APUE之线程(三)
- APUE之线程(四)
- APUE之线程(六)
- APUE之线程初探
- APUE之线程属性
- APUE之线程同步
- apue学习之线程创建
- APUE学习-线程(1)
- 李林apue之线程的封装
- APUE之线程创建与终止
- APUE线程
- APUE学习(五):线程与进程(API与概念部分)
- apue学习笔记(第十一章 线程)
- 程序员自学之旅(五)线程
- Java多线程之线程池(五)
- (九) 一起学 Unix 环境高级编程 (APUE) 之 线程
- BestCoder Round #76 (div.2)
- BZOJ-2659 算不出的算式 找规律找规律找规律(说三遍)
- leatcode 9.Palindrome Number
- Runtime使用场景
- java项目相对路径问题
- APUE之线程(五)
- Spring操作Mongodb
- 数据结构与算法——AVL树简介
- delegate、notification、KVO的使用场景总结
- 软件工程-web软件设计
- Android UI 控件之TextView
- 【架构篇】Android移动app架构设计浅谈
- 小白笔记--------------二分搜索算法
- 字符串应用(2)基本例程