线程同步
1. semophore 信号量
接口函数
int sem_destroy(sem_t *); int sem_getvalue(sem_t *restrict, int *restrict); int sem_init(sem_t *, int, unsigned); int sem_post(sem_t *); int sem_timedwait(sem_t *restrict, const struct timespec *restrict); int sem_trywait(sem_t *); int sem_wait(sem_t *); 简单用法: #include <semaphore.h> sem_t bin_sem; res = sem_init(&bin_sem, 0, 0); sem_wait(&bin_sem); //对应于P(sem)操作
//do something sem_post(&bin_sem); //对应于V(sem)操作 sem_destroy(&bin_sem);
2. Mutex 互斥
头文件以及函数
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex));
int pthread_mutex_timedlock(pthread_mutex_t *, const struct timespec *);
int pthread_mutex_trylock(pthread_mutex_t *);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
使用
pthread_mutex_t mutex;
pthread_mutex_init(&mutex,NULL);
pthread_mutex_lock(&mutex);
//do something
pthread_mutex_unlock(&mutex);
3.条件变量
int pthread_cond_broadcast(pthread_cond_t *);
int pthread_cond_destroy(pthread_cond_t *);
int pthread_cond_init(pthread_cond_t *restrict, const pthread_condattr_t *restrict);
int pthread_cond_signal(pthread_cond_t *);
int pthread_cond_timedwait(pthread_cond_t *restrict, pthread_mutex_t *restrict, const struct timespec *restrict);
int pthread_cond_wait(pthread_cond_t *restrict, pthread_mutex_t *restrict);
互斥量与条件变量经常一起使用,实现生产者与消费者之间的同步与互斥。
例如多个生产者,多个消费者都对同一缓存区进行操作的情况。
#include <pthread.h>
struct data{}; //数据块
int n; //缓存区数据块个数
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //缓存区互斥访问
pthread_mutex_t mutex_n = PTHREAD_MUTEX_INITIALIZER; //对n的互斥访问
pthread_cond_t wcond = PTHREAD_COND_INITIALIZER; //写条件变量
pthread_cond_t rcond = PTHREAD_COND_INITIALIZER; //读条件变量
//初始化操作
n = 10; //假设缓存区有10个数据块
produce线程函数
pthread_mutex_lock(&mutex_n);
//线程同步,若缓存区满则等待消费者取走数据
while(n <= 0)
pthread_cond_wait(&wcond,&mutex_n);
pthread_mutex_lock(&mutex); //缓存区有空闲,申请访问缓存区
//对缓存区操作
pthread_mutex_unlock(&mutex);
//写完成,唤醒读进程
pthread_cond_signal(&rcond);
//对缓存区状态信息修改
n--; //很重要 同步的问题
pthread_mutex_unlock(&mutex_n);
customer线程函数
pthread_mutex_lock(&mutex_n);
//线程同步,若缓存区空等待生产者写入数据
while(n >= 10)
pthread_cond_wait(&rcond,&mutex_n);
pthread_mutex_lock(&mutex); //不为空,申请访问缓存区
//从一个有效缓存区消费
pthread_mutex_unlock(&mutex);
//取走数据,唤醒生产者
pthread_cond_signal(&wcond);
//更改状态信息
n++; //很重要 确保消费成功再更改状态
pthread_mutex_unlock(&mutex_n);
4.读写锁
读写锁与互斥量类似,不过读写锁允许更高的并行性。
当读写锁是加锁状态时,在这个锁被解锁之前,所有试图对这个锁加锁的线程都会被阻塞。
当读写锁在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但写锁需等待所有读锁全部释放。
int pthread_rwlock_destroy(pthread_rwlock_t *);
int pthread_rwlock_init(pthread_rwlock_t *restrict, const pthread_rwlockattr_t *restrict);
int pthread_rwlock_rdlock(pthread_rwlock_t *);
int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict, const struct timespec *restrict);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict, const struct timespec *restrict);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
int pthread_rwlock_trywrlock(pthread_rwlock_t *);
int pthread_rwlock_unlock(pthread_rwlock_t *);
int pthread_rwlock_wrlock(pthread_rwlock_t *);
5. Spinlocks 自旋锁
int pthread_spin_destroy(pthread_spinlock_t *);
int pthread_spin_init(pthread_spinlock_t *, int);
int pthread_spin_lock(pthread_spinlock_t *);
int pthread_spin_trylock(pthread_spinlock_t *);
int pthread_spin_unlock(pthread_spinlock_t *);
进程同步/通信
POSIX IPC实现
1. Semaphore 信号量
简单过程:
semaphore sv = 1;
loop forever {
P(sv);
critical code section;
V(sv);
noncritical code section;
}
头文件以及函数:
#include <sys/sem.h>
int semctl(int sem_id, int sem_num, int command, ...);
int semget(key_t key, int num_sems, int sem_flags);
int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);
2.Share Memory 共享内存
头文件以及函数
#include <sys/shm.h>
void *shmat(int shm_id, const void *shm_addr, int shmflg);
int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
int shmdt(const void *shm_addr);
int shmget(key_t key, size_t size, int shmflg);
3.Message Queues 消息队列
头文件以及函数
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
int msgget(key_t key, int msgflg);
int msgrcv(int msqid, void *msg_ptr, size_t msg_sz, long int msgtype, int msgflg);
int msgsnd(int msqid, const void *msg_ptr, size_t msg_sz, int msgflg);