Linux多线程

c++多线程

https://blog.csdn.net/hffhjh111/article/details/53141324

https://blog.csdn.net/dcrmg/article/details/53912941

https://www.cnblogs.com/wangguchangqing/p/6134635.html

参考

Linux站式编程

https://www.cnblogs.com/xiehongfeng100/p/4620852.html

https://blog.csdn.net/snow_5288/article/details/73028514

https://blog.csdn.net/lee1054908698/article/details/54633056

进程和线程的区别(面试常考)

https://blog.csdn.net/kuangsonghan/article/details/80674777

根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位

在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)

内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。

包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
 

控制线程和线程标识符

Linux在创建线程的时候,会有一个控制线程(主线程)来控制新线程的工作。每个线程也有一个线程ID,是一个无符号的长整型。

线程操作

创建线程

 

#include <pthread.h>
int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void*), void *restrict arg);

返回值:成功返回0,失败返回错误号。以前学过的系统函数都是成功返回0,失败返回-1,而 错误号保存在全局变量errno中,而pthread库的函数都是通过返回值返回错误号,虽然每个线 程也都有一个errno,但这是为了兼容其它函数接口而提供的,pthread库本身并不使用它,通 过返回值返回错误码更加清晰。

终止线程

如果需要只终止某个线程而不终止整个进程,可以有三种方法: 从线程函数return。这种方法对主线程不适用,从main 函数return相当于调用exit 。 一个线程可以调用pthread_cancel 终止同一进程中的另一个线程。 线程可以调用pthread_exit终止自己。

创建线程


void printids(const char *s)
{
    cout<<s;
    pid_t pid;
    pthread_t tid;//线程id
    pid=getpid();
    tid=pthread_self();
    cout<<"pid:"<<pid<<" tid:"<<tid<<" ";
    printf("tid:%u\n",tid);
    //cout<<"pid:"<<pid<<" tid:"<<tid<<" "<<hex/*16进制*/<<tid<<endl;
    //printf("%s pid %u tid %u (0x%x)\n",s,(unsigned int)pid,(unsigned int)tid,(unsigned int)tid);
}
void *thread1(void *arg)//create的第三个参数 创建线程之后执行
{
    printids("New thread:");
    return NULL;
}
void fun1()
{
    pthread_t ntid;
    int err;
    cout<<"thread"<<endl;
    err=pthread_create(&ntid, NULL, thread1,NULL);//创建线程
    if(err!=0)//正确返回0
    {
        //perror("");
        /*
         由于pthread_create 的错误码不保存在errno 中,因此不能直接用perror(3) 打印错误信息,可以 先用strerror(3)把错误码转换成错误信息再打印。
         */
         fprintf(stderr, "can't create thread: %s\n",strerror(err));
        exit(1);
    }
    printids("Main thread:");
    sleep(1);
}

可知在Linux上,thread_t类型是一个地址值,属于同一进程的多个线程调用getpid(2)可以得到 相同的进程号,而调用pthread_self(3) 得到的线程号各不相同。

#include <pthread.h>
int pthread_join(pthread_t thread, void **value_ptr);

返回值:成功返回0,失败返回错误号 调用该函数的线程将挂起等待,直到id为thread的线程终止。thread线程以不同的方法终止,通

过pthread_join得到的终止状态是不同的,总结如下:

如果thread线程通过return返回,value_ptr 所指向的单元里存放的是thread线程函数的返

回值。
如果thread线程被别的线程调用pthread_cancel 异常终止掉,value_ptr 所指向的单元里存

放的是常数PTHREAD_CANCELED。 如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传

给pthread_exit的参数。 如果对thread线程的终止状态不感兴趣,可以传NULL 给value_ptr 参数。

//线程终止
void *thr_fn1(void *arg)
{
    printf("thread 1 returning\n"); return (void *)1;
}
void *thr_fn2(void *arg)
{
    printf("thread 2 exiting\n");
    pthread_exit((void *)2);
}
void *thr_fn3(void *arg)
{
    while(1)
    {
        printf("thread 3 writing\n");
        sleep(1);
    }
}
void fun2()
{
    void *tret;
    pthread_t tid;
    pthread_create(&tid, NULL, thr_fn1, NULL); pthread_join(tid, &tret);
    printf("thread 1 exit code %d\n", tret);
    pthread_create(&tid, NULL, thr_fn2, NULL);
    pthread_join(tid, &tret);
    printf("thread 2 exit code %d\n", tret);
    pthread_create(&tid, NULL, thr_fn3, NULL); sleep(3);
    pthread_cancel(tid);
    pthread_join(tid, &tret);
    printf("thread 3 exit code %d\n", tret);
}

取消线程阻塞的结果

//线程终止
void *thr_fn1(void *arg)
{
    while(1){
    printf("thread 1 returning\n"); sleep(1);
    }
    //return (void *)1;
}
void *thr_fn2(void *arg)
{
    while (1){
    printf("thread 2 exiting\n");sleep(1);
    }
    pthread_exit((void *)2);
}
void *thr_fn3(void *arg)
{
    while(1)
    {
        printf("thread 3 writing\n");
        sleep(1);
    }
}
void fun2()
{
    void *tret;
    pthread_t tid;
    pthread_create(&tid, NULL, thr_fn1, NULL);
    //pthread_join(tid, &tret);
    printf("thread 1 exit code %d\n", tret);
    pthread_create(&tid, NULL, thr_fn2, NULL);
    //pthread_join(tid, &tret);
    printf("thread 2 exit code %d\n", tret);
    pthread_create(&tid, NULL, thr_fn3, NULL); sleep(3);
    //pthread_cancel(tid);
    pthread_join(tid, &tret);
    printf("thread 3 exit code %d\n", tret);
}

 

线程清理

在取消线程之后,要通过clearup_push,clearup_pop对环境进行清理。

参考https://blog.csdn.net/longbei9029/article/details/72871714

如果线程是通过从它的启动历程中返回而终止的话,那么它的清理处理程序就不会被调用,还要注意清理程序是按照与它们安装时相反的顺序被调用的。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
using namespace std;

//线程终止
void clear(void *arg)//线程清理
{
    cout<<"thread clear:"<<(char*)arg<<endl;
}
void *thr_fn1(void *arg)
{
    pthread_cleanup_push(clear, (void*)"first");
    pthread_cleanup_push(clear, (void*)"second");
    printf("thread 1 returning\n");
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);
    return (void *)1;//清理线程不会启动
}
void *thr_fn2(void *arg)
{
    pthread_cleanup_push(clear, (void*)"first");
    pthread_cleanup_push(clear, (void*)"second");
    printf("thread 2 exiting\n");
    pthread_exit((void *)2);
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);
    //pthread_exit((void *)2);
}
void *thr_fn3(void *arg)
{
    while(1)
    {
        printf("thread 3 writing\n");
        sleep(1);
    }
}
void fun2()
{
    void *tret;
    pthread_t tid;
    pthread_create(&tid, NULL, thr_fn1, NULL);
    pthread_join(tid, &tret);
    printf("thread 1 exit code %d\n", tret);
    pthread_create(&tid, NULL, thr_fn2, NULL);
    pthread_join(tid, &tret);
    printf("thread 2 exit code %d\n", tret);
    pthread_create(&tid, NULL, thr_fn3, NULL); sleep(3);
    pthread_cancel(tid);
    pthread_join(tid, &tret);
    printf("thread 3 exit code %d\n", tret);
}
int main(int argc, const char * argv[])
{
    fun2();
    return 0;
}

线程分离

通过线程分离,让其他线程不会等待他的结束,运行结束后,线程终止,资源及时释放。

void *threaddeal(void *arg)
{
    pthread_detach(pthread_self());//线程分离
    printf("这是第%d个线程\n",*((int*)arg));
    pthread_exit(NULL);
}
void Detach()//线程分离
{
    int count=20;
    pthread_t tid;
    for(int i=0;i<count;i++)
    {
        int *p=&i;
        int ret=pthread_create(&tid, NULL, threaddeal, (void *)p);
        if(ret==0)
        {
            //printf("%dsuccess:",i);
            //pthread_detach(tid);//线程分离
        }
        else
        {
            cout<<"Failed!"<<endl;
        }
    }
    //pthread_exit(NULL);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值