天天看点

线程间的互斥和信号量

线程间的互斥

互斥锁是用来保护一段临界区的,它保证某段时间内只有一个线程在执行一段代码或者访问某个资源。

  1. 函数
#include <pthread.h>
	pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
	//普通锁,同一线程可重复加锁,解锁一次释放锁,先等待锁的进程先获得锁
    pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALZER_NP;
    //嵌套锁,同一线程可重复加锁,解锁同样次数才可释放锁,先等待锁的进程先获得锁
    pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
    //纠错锁,同一线程不能重复加锁,加上的锁只能由本线程解锁,先等待锁的进程先获得锁
    pthread_mutex_t adaptivemutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
    //自适应锁,同一线程可重加锁,解锁一次生效,所有等待锁的线程自由竞争
    int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *mutexattr);//互斥锁初始化 attr为null表示默认属性
    int pthread_mutex_lock(pthread_mutex_t *mutex);//锁定
    int pthread_mutex_trylock(pthread_mutex_t *mutex);//预锁定
    int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁
    int pthread_mutex_destroy(pthread_mutex_t *mutex);//销毁互斥
           
  • pthread_mutex_init(),初始化一个mutex变量,attr为属性,NULL表示使用默认属性
  • pthread_mutex_lock()使用互斥锁上锁,直至使用pthread_mutex_unlock()解锁。当线程执行到pthread_mutex_lock()函数处时,该锁在被另一个线程使用则此线程被阻塞直至另一个线程释放此互斥锁。
  • 互斥锁使用完毕之后使用pthread_mutex_destroy()释放资源
  1. 示例
class PthreadMutexTest
{
    public:
        PthreadMutexTest()
        {
            pthread_mutex_init(&mutex,NULL);//初始化
            
        }
        ~PthreadMutexTest()
        {
            pthread_mutex_destroy(&mutex);//销毁
        }
        
        void* producter_f(void* arg);
        void* consumer_f(void* arg);
        int ProducterAndConsumerTest();//通过静态函数回调
        static void* proCbk(void* arg);
        static void* conCbk(void* arg);
        
    private:
        static PthreadMutexTest* CurPtM;
        int buffItem=0;							/*缓冲区计数值*/
        pthread_mutex_t mutex;							/*互斥区*/
        void setCurPtM()
        {
            CurPtM = this;
        }
};
PthreadMutexTest* PthreadMutexTest::CurPtM = NULL;//初始化,类静态数据成员只能在类外初始化,且只能初始化一次。
void* PthreadMutexTest::proCbk(void* arg)
{
    return CurPtM->producter_f(arg);
}
void* PthreadMutexTest::conCbk(void* arg)
{
    return CurPtM->consumer_f(arg);
}
void* PthreadMutexTest::producter_f(void* arg)
{
    int* running  = static_cast<int*>(arg);
    while(*running )
    {
        pthread_mutex_lock(&mutex);//互斥加锁
        buffItem++;
        printf("product ,num:%d\n",buffItem);
        pthread_mutex_unlock(&mutex);

    }
    return nullptr;
}
void* PthreadMutexTest::consumer_f(void* arg)
{
    int*  running  = static_cast<int*>(arg);
    while(*running )
    {
        pthread_mutex_lock(&mutex);
        buffItem--;
        printf("use,num:%d\n",buffItem);
        pthread_mutex_unlock(&mutex);
    }
    return nullptr;
}
int  PthreadMutexTest::ProducterAndConsumerTest()
{
    setCurPtM();
    pthread_t producter_t,consumer_t;
    int running = 1;
    pthread_create(&producter_t,NULL,proCbk,&running);//建立生产者线程
    pthread_create(&consumer_t,NULL,conCbk,&running);//建立消费者线程
    usleep(1);//等待线程建立完毕
    running  = 0;
    pthread_join(consumer_t,NULL);
    pthread_join(producter_t,NULL);
    return 0;
}
           

线程间使用信号量

线程的信号量与进程的信号量类似,使用线程的信号量可以高效的完成基于线程的资源计数。

  1. 函数
#include <semaphore.h>
int sem_init(sem_t *sem,int pshared,unsigned int val);//初始化信号量
int sem_post(sem_t *sem);//线程信号量增加函数,P
int sem_wait(sem_t *sem);//线程信号量等待(减少)函数,V,
int sem_trywait(sem_t *sem);//
int sem_destroy(sem_t *sem);//销毁
           
  • sem_init(),初始化信号量,sem指向信号量结构的一个指针,pshared用于表示信号量的共享类型,不为0表示可以在进程间共享,否则只能在线程中共享,val信号量初始值
  • sem_post(),增加信号的值,每次增加1
  • sem_wait(),减少信号量,信号量值为0会阻塞线程直至大于0
  • sem_destroy(),使用完毕之后释放资源
  1. 示例
#include <semaphore.h>
class PthreadSemaphoreTest
{
    public:
        PthreadSemaphoreTest()
        {
            sem_init(&sem,0,8);//初始化
        }
        ~PthreadSemaphoreTest()
        {
            sem_destroy(&sem);
        }
        
        void* producter_f(void* arg)
        {
            int* running = static_cast<int*>(arg);
            while(running)
            {
                usleep(1);
                sem_post(&sem);//P
                int semval=0;
                sem_getvalue(&sem,&semval);
                printf("producter:%d\n",semval);
            }
            return NULL;
        }
        void* consumer_f(void* arg) 
        {
            int* running = static_cast<int*>(arg);
            while(running)
            {
                usleep(1);
                sem_wait(&sem);//V
                int semval=0;
                sem_getvalue(&sem,&semval);
                printf("consumer:%d\n",semval);
            }
            return NULL;
        }
        static void* proCbk(void* arg)
        {
            return CurPtS->producter_f(arg);
        }
        static void* conCbk(void* arg)
        {
            return CurPtS->consumer_f(arg);
        }
        int ProducterAndConsumerTest()
        {//通过静态函数回调
            setCurPtM();
            pthread_t producter_t,consumer_t;
            int running = 1;
            pthread_create(&producter_t,NULL,proCbk,&running);
            pthread_create(&consumer_t,NULL,conCbk,&running);
            usleep(1);
            running = 0;
            pthread_join(producter_t,NULL);
            pthread_join(consumer_t,NULL);
            return 0;
        }
    private:
        static PthreadSemaphoreTest* CurPtS;
        sem_t sem;							/*信号量*/
        void setCurPtM()
        {
            CurPtS = this;
        }
};
PthreadSemaphoreTest* PthreadSemaphoreTest::CurPtS = NULL;
           

Linux网络编程(第二版) 第四章 读书笔记