c++多线程

多线程

创建线程

int pthread_create(pthread_t *restrict __newthread, const pthread_attr_t *restrict __attr, void (__start_routine)(void *), void *restrict __arg)

参数分别为,线程号,状态,回调函数,回调函数的参数

pthread_create(&threadId1, NULL, handleThread1, &num1)

回调函数

void *handleThread1(void *arg)
{
    /*线程分离*/
    pthread_detach(pthread_self());
    int num = *(int *)arg;
    int num = 1;
     while(1)
     {
         printf("num=%d\n", num);
         num+=2;
         /*休眠两秒*/
         sleep(2);
     }
    /*线程退出*/
    pthread_exit(NULL);
}

线程分离

    防在线程回调函数第一句
    /*线程分离:线程结束后系统自动回收*/
    pthread_detach(pthread_self());
    pthread_self(),返回线程号
通过状态来分离线程
/*初始化线程状态*/
    pthread_attr_t threadAttr;
    pthread_attr_init(&threadAttr);


    /*设置线程分离状态*/
    int ret=pthread_attr_setdetachstate(&threadAttr,PTHREAD_CREATE_DETACHED);
    if(ret!=0)
    {
        perror("phtread_attr_setdetachstate:");
        /*退出线程*/
        _exit(-1);
    }
    pthread_t threadId;
    ret=pthread_create(&threadId, &threadAttr, thread_func, NULL);
        if(ret!=0)
    {
        perror("phtread_create:");
        /*退出线程*/
        _exit(-1);
    }
    /*释放线程属性*/
    pthread_attr_destroy(&threadAttr);

线程回收

    /*一旦线程已经被分离,pthread_join就不能回收他的资源,该线程结束后自动回收*/
    pthread_join(threadId1, NULL);

线程退出

    /*线程退出*/
    pthread_exit(NULL);

线程取消

pthread_cancel(threadId);

函数的形参

​ 传入参数:不可修改

​ 如果是字符串加上const属性

​ 如果是整型,值传递

​ 传出参数:可修改的

互斥锁(互斥量)

一种简单的加锁方式,来控制对共享资源的访问,两种状态,加锁(lock),解锁(unlock)

互斥锁的数据类型:pthread_mutex_t

pthread_mutex_init()函数
int pthread_mutex_init(pthread_mutex_t *__mutex, const pthread_mutexattr_t *__mutexattr)
pthread_mutex_t mutex;
pthread_mutex_init(&mutex,NULL);

pthread_mutex_lock()函数

pthread_mutex_unlock()函数

pthread_mutex_destroy()函数

/*全局变量*/
pthread_mutex_t mutex;
void painter(const char* str)
{
    if(str==NULL)
    {
        return;
    }
    while(*str!='\0')
    {
        cout << *str ;
        fflush(stdout);
        sleep(1);
        str++;
    }
    cout << endl;
    return;
}
void* threadFunc1(void* arg)
{

    const char *str1 = "hello";
    /*加锁*/
    pthread_mutex_lock(&mutex);
    painter(str1);
    /*解锁*/
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}
void* threadFunc2(void* arg)
{
    const char *str2 = "world";
    /*加锁*/
    pthread_mutex_lock(&mutex);
    painter(str2);
    /*解锁*/
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}
int main()
{
    /*初始化一把锁*/
    pthread_mutex_init(&mutex,NULL);
    pthread_t threadId1;
    int ret=pthread_create(&threadId1, NULL, threadFunc1, NULL);
    if(ret!=0)
    {
        perror("create:");
        _exit(-1);
    }
    pthread_t threadId2;
    ret=pthread_create(&threadId2, NULL, threadFunc2, NULL);
    if(ret!=0)
    {
        perror("create:");
        _exit(-1);
    }
    pthread_join(threadId1,NULL);
    pthread_join(threadId2,NULL);
    /*释放锁*/
    pthread_mutex_destroy(&mutex);
    return 0;
}

解决死锁:

1、检测到当前程序死锁

​ (1)内核态阻塞

​ (2)用户态阻塞(死循环&进程占用的cpu较高)

2、所有的程序的加锁方式必须按照顺序

​ 所有程序的解锁方式也必须按照顺序

读写锁

pthread_rwlock_init函数

pthread_rwlock_destroy函数

pthread_rwlock_rdlock函数

pthread_rwlock_wrlock函数 //写锁,其他线程不允许读或写操作(即拿不到写锁,也拿不到读锁)

pthread_rwlock_unlock函数

#include<iostream>
#include<pthread.h>
#include<unistd.h>
using namespace std;
pthread_rwlock_t rwlock;
int g_num = 100;
void *threadFunc1(void *arg)
{
//     while(1)
// {
    pthread_rwlock_rdlock(&rwlock);
        for (int i = 0; i < 10;i++)
    {
        cout << "threadFunc1:" << g_num << endl;
        usleep(100);
    }
    pthread_rwlock_unlock(&rwlock);
// }
    pthread_exit(NULL);
}
void* threadFunc2(void* arg)
{
// while(1)
// {
    pthread_rwlock_rdlock(&rwlock);
    for (int i = 0; i < 10;i++)
    {
        cout << "threadFunc2:" << g_num << endl;
        usleep(100);
    }
        pthread_rwlock_unlock(&rwlock);
// }
    pthread_exit(NULL);
}
void* threadFunc3(void* arg)
{
    pthread_rwlock_wrlock(&rwlock);
    sleep(10);
    g_num++;
    pthread_rwlock_unlock(&rwlock);
    pthread_exit(NULL);
}
void* threadFunc4(void* arg)
{
    pthread_rwlock_wrlock(&rwlock);
    sleep(10);
    g_num++;
    pthread_rwlock_unlock(&rwlock);
    pthread_exit(NULL);
}
int main()
{
    //初始化读写锁
    pthread_rwlock_init(&rwlock, NULL);
    pthread_t threadId1;
    int ret=pthread_create(&threadId1, NULL, threadFunc1, NULL);
    if(ret!=0)
    {
        perror("create:");
        _exit(-1);
    }
    pthread_t threadId2;
    ret=pthread_create(&threadId2, NULL, threadFunc2, NULL);
    if(ret!=0)
    {
        perror("create:");
        _exit(-1);
    }
        pthread_t threadId3;
    ret=pthread_create(&threadId3, NULL, threadFunc3, NULL);
    if(ret!=0)
    {
        perror("create:");
        _exit(-1);
    }
    pthread_t threadId4;
    ret=pthread_create(&threadId4, NULL, threadFunc4, NULL);
    if(ret!=0)
    {
        perror("create:");
        _exit(-1);
    }
    pthread_join(threadId1,NULL);
    pthread_join(threadId2,NULL);
    pthread_join(threadId3,NULL);
    pthread_join(threadId4,NULL);
    //释放读写锁
    pthread_rwlock_destroy(&rwlock);
    return 0;
}

条件变量

条件变量本身不是锁,用来阻塞一个线程,直到某特殊情况发生,通常条件变量和互斥锁同时使用

条件变量类型:pthread_cond_t

pthread_cond_init函数

pthread_cond_destroy函数

pthread_cond_singal函数

pthread_cond_wait函数:该函数在使用时会自动解锁

    pthread_mutex_lock(&g_mutex);
    while(g_head==NULL)
    {
    	
        pthread_cond_wait(&g_cond, &g_mutex);//解锁并等待条件变量被满足 ->  pthread_cond_singal()发信号
        								//当条件被满足时(接受到条件变量),解除阻塞,并重新上锁
    }

信号量

类型:sem_t

当信号量大于0时,有访问权限

p操作:一次p操作使信号量-1,v操作:一次v操作使信号量+1

sem_init函数

sem_destroy函数

sem_wait函数加锁 p操作

sem_post函数解锁 v操作

信号量p操作(-1)=加锁

信号量v操作(+1)=解锁

sem_getvalue函数,获得信号量的值

sem占用资源较少

一般使用互斥锁+条件变量,sem的使用场景相对较少

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值