POSIX信号量与互斥锁

来源:互联网 发布:爱知工科大学怎么样 编辑:程序博客网 时间:2024/05/16 20:52
3种用于线程同步的机制: POSIX信号量,互斥锁和条件变量
一.POSIX信号量
常用的POSIX信号量函数如下
    int sem_init(sem_t *sem, int pshared, unsigned int value);//初始化一个信号量
    int sem_destroy(sem_t *sem); //销毁信号量
    
    int sem_wait(sem_t *sem); // 以原子操作的方式将信号量的值减1
    int sem_trywait(sem_t *sem); //非阻塞版本
    int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
    
    int sem_post(sem_t *sem); // 以原子操作方式将信号量的值加1
    

二.POSIX互斥锁
    互斥锁可以用来保护关键代码段,以确保独占式的访问.
POSIX互斥锁相关函数
    int pthread_mutex_destroy(pthread_mutex_t *mutex);//销毁互斥锁
    int pthread_mutex_init(pthread_mutex_t *restrict mutex,
              const pthread_mutexattr_t *restrict attr);

    //实际上只是把互斥锁的各个字段初始化为0          
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
      
    int pthread_mutex_lock(pthread_mutex_t *mutex);  //以原子操作方式给互斥锁加锁
    int pthread_mutex_trylock(pthread_mutex_t *mutex);//非阻塞版本
    int pthread_mutex_unlock(pthread_mutex_t *mutex);// 以原子操作方式给互斥锁解锁

三. 生产者消费者问题

#include <unistd.h>#include <sys/types.h>#include <pthread.h>#include <semaphore.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#define ERR_EXIT(m) \do \{\perror(m); \exit(EXIT_FAILURE); \}while(0)#define CONSUMERS_COUNT 1#define PRODUCERS_COUNT 5#define BUFFSIZE 10  // 缓冲区大小int g_buffer[BUFFSIZE]; /// 产品ID保存在缓冲区中unsigned short in=0;  // 从in位置放产品unsigned short out=0;  // 从out的位置消费产品unsigned short produce_id =0;  // 产品IDunsigned short consume_id =0;  // 消费产品IDsem_t  g_sem_full;  //full信号量sem_t  g_sem_empty;  //empty信号量pthread_mutex_t   g_mutex;  // 互斥锁// 创建的线程ID保存在g_thread中pthread_t g_thread[CONSUMERS_COUNT+PRODUCERS_COUNT];///消费者void* consume(void* arg){int num = (int)arg;int i;while(1){printf("%d wait buffer not empty\n",num);sem_wait(&g_sem_empty);pthread_mutex_lock(&g_mutex);//打印仓库状态for(i=0;i<BUFFSIZE;++i){printf("%02d ",i);if(g_buffer[i] == -1)printf("%s","null");elseprintf("%d",g_buffer[i]);if(i == out)printf("\t<--consume");printf("\n");}// 消费产品consume_id = g_buffer[out];printf("%d begin consume product %d\n",num,consume_id);g_buffer[out] = -1;  // 取走产品,得把缓冲区设置为-1out = (out+1)%BUFFSIZE;printf("%d end consume product %d\n",num,consume_id);pthread_mutex_unlock(&g_mutex);sem_post(&g_sem_full);sleep(1);}return NULL;}//// 生产者void* produce(void* arg){int i;int num = (int)arg;while(1){printf("%d wait buffer not full\n",num);sem_wait(&g_sem_full);pthread_mutex_lock(&g_mutex);// 打印仓库的状态for(i=0;i<BUFFSIZE;++i){printf("%02d ",i);if(g_buffer[i] == -1)printf(" %s","null");elseprintf("%d ",g_buffer[i]);if(i == in)printf("\t<--produce");printf("\n");}// 生产产品printf("%d begin produce produce %d \n",num,produce_id);g_buffer[in] = produce_id;in = (in+1)%BUFFSIZE;printf("%d end produce product %d\n",num,produce_id++);pthread_mutex_unlock(&g_mutex);sem_post(&g_sem_empty);sleep(5);}return NULL;}int main(void ){int i=0;for(i=0;i<BUFFSIZE;++i)g_buffer[i] = -1;  // 初始化仓库都为-1// 初始化信号量sem_init(&g_sem_full,0,BUFFSIZE); //g_sem_full 信号的初始值为BUFFSIZEsem_init(&g_sem_empty,0,0);//初始化互斥锁pthread_mutex_init(&g_mutex,NULL);/// 创建消费者线程for(i=0;i<CONSUMERS_COUNT;++i)pthread_create(&g_thread[i],NULL,consume,(void*)i);/// 创建生产者线程for(i=0;i<PRODUCERS_COUNT;++i)pthread_create(&g_thread[CONSUMERS_COUNT+i],NULL,produce,(void*)i);// 等待线程的结束for(i=0;i<CONSUMERS_COUNT+PRODUCERS_COUNT;++i)pthread_join(g_thread[i],NULL);return 0;}


四. 自旋锁与读写锁

1.自旋锁
    (1)自旋锁类似于互斥锁,它的性能比互斥锁更高
    (2)自旋锁与互斥锁很重要的一个区别在于,线程在申请自旋锁的时候,线程不会被挂起,处于忙等待状态
      int pthread_spin_destroy(pthread_spinlock_t *lock);
      int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
      int pthread_spin_lock(pthread_spinlock_t *lock);
      int pthread_spin_trylock(pthread_spinlock_t *lock);
      int pthread_spin_unlock(pthread_spinlock_t *lock);

2.读写锁
    (1)只要没有线程持有给定的读写锁用于写,那么任意数目线程可以持有读写锁用于读.
    (2)仅当没有线程持有某个给定的读写锁用于读或者用于写时才能分配读写锁用于写.
    (3)读写锁用于读称为共享锁,读写锁用于写称为排他锁.
    int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
    int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
              const pthread_rwlockattr_t *restrict attr);
    int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
    int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
   
    int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
    int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
    int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);


0 0
原创粉丝点击