b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

Linux多线程学习

电脑杂谈  发布时间:2020-06-11 08:19:53  来源:网络整理

linux的进程与线程_linux多线程服务器设计_linux 进程与线程

首先,编写一个耗时的单线程程序:

#include<cstdio>
#include<unistd.h>
int main()
{
    sleep(5);
    printf("program exited.\n");
}

编译并运行该程序,该程序将在5秒钟后输出,并且在睡眠期间不再响应其他消息或执行其他操作. 为了更好地处理这一耗时的操作,我们需要使用多线程编程.

首先复制书中的内容:

进程和线程都是操作系统概念. 进程是应用程序的执行实例. 每个进程都由一个私有虚拟地址空间,代码,数据和其他各种系统资源组成. 进程终止时,进程在操作期间创建的资源将被销毁. 进程终止时,将释放或关闭系统资源.

线程是进程内部的执行单元. 系统创建进程后,实际上会启动执行该进程的主执行线程. 主执行线程以函数地址(例如主函数)的形式向操作系统提供程序的起点. 主执行线程终止,并且进程相应终止.

每个进程至少具有一个主执行线程. 用户不需要主动创建它. 它是由系统自动创建的. 用户根据需要在应用程序中创建其他线程,并且多个线程在同一进程中同时运行. 进程中的所有线程都在该进程的虚拟地址空间中,并且这些虚拟地址空间,全局变量和系统资源一起使用,因此线程之间的通信非常方便,并且多线程技术的应用也越来越多广泛传播.

多线程可以实现并行处理,避免了某些任务长时间占用CPU时间. 要注意的一件事是,当前某些计算机是单处理器(CPU). 为了运行所有这些线程,操作系统为每个独立线程安排一些CPU时间. 操作系统以旋转方式向线程提供时间片. 给人一种幻想,即这些线程正在同时运行. 由此可以看出,如果两个非常活跃的线程抓住了CPU的控制权,则程之间切换时它们将消耗大量CPU资源,但会降低系统性能. 多线程编程中应注意这一点.

具有以下特征的程序可以使用线程:

多线程还可以用于串行程序,以模拟并行执行. 一个很好的例子是经典的Web浏览器,它在单CPU计算机上运行,​​可以同时“显示”很多东西.

使用线程编程的几种常见模型:

接下来看看实现多线程编程的接口pthread.

一个,线程管理

1. 创建并结束线程

功能:

int pthread_create(pthread_t *tidp,const pthread_attr_t *attr,(void*)(*start_rtn)(void*),void *arg);
void pthread_exit(void* retval);
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);

创建线程:

linux 进程与线程_linux的进程与线程_linux多线程服务器设计

最初,main函数包含一个默认线程. 其他线程需要程序员显式创建它们. pthread_create创建一个新线程并运行它. 可以在程序中的任何位置调用此函数.

Pthread_create参数和返回值:

第一个参数是指向线程标识符的指针. 无法设置为NULL.

第二个参数用于设置线程属性. 可以将NULL设置为默认值.

第三个参数是线程运行函数的起始地址,它是线程将执行一次的C函数.

最后一个参数是传递给运行函数的参数. 必须将其转换为在传递时指向void的指针类型. 如果不传递任何参数,则可以将其设置为NULL.

如果成功,则返回0,否则返回错误号.

一个进程可以创建的最大线程数取决于系统实现.

创建后,线程称为对等端,并且可以创建其他线程. 线程之间没有指定的结构和依赖性.

有这么一对问题和答案:

问: 创建线程后,如何知道操作系统何时安排线程运行?

A: 除非使用线程调度机制,否则执行线程的时间和地点取决于操作系统的实现. 一个强大的程序不应该依赖于线程执行的顺序.

也就是说,多线程程序的运行结果可能不确定,因为尚不清楚系统何时运行该线程.

线程属性:

线程具有由pthread_attr_t表示的属性,这些属性必须在处理结构之前初始化,并且在使用后需要取消初始化. 我们使用pthread_attr_init函数对其进行初始化,并使用pthread_attr_destroy删除其初始化. 还有其他功能可以查询和设置线程属性结构的指定属性.

线程属性结构如下:

typedef struct
{
    int                   etachstate;      //线程的分离状态
    int                   schedpolicy;     //线程调度策略
    structsched_param     schedparam;      //线程的调度参数
    int                   inheritsched;    //线程的继承性
    int                   scope;           //线程的作用域
    size_t                guardsize;       //线程栈末尾的警戒缓冲区大小
    int                   stackaddr_set;   //线程的栈设置
    void*                 stackaddr;       //线程栈的位置
    size_t                stacksize;       //线程栈的大小
}pthread_attr_t;

linux多线程服务器设计_linux的进程与线程_linux 进程与线程

在调用pthread_attr_init之后,pthread_t结构中包含的内容是操作系统实现所支持的线程的所有属性的默认值.

如果要删除pthread_attr_t结构的初始化linux多线程服务器设计,则可以调用pthread_attr_destroy函数. 如果为pthread_attr_init为属性对象分配了动态内存空间,则pthread_attr_destroy还将使用无效值初始化属性对象,因此,如果由pthread_attr_destroy删除初始化后的pthread_attr_t结构由pthread_create函数调用,它将导致它返回一个错误.

线程属性的其他功能和用法将在后面讨论.

结束终止:

有几种方法可以结束线程:

pthread_exit用于显式退出线程. 通常,当线程完成其工作或不再需要它并退出线程时,将调用pthread_exit()函数. 如果main函数在调用pthread_exit()之后退出,尽管main中没有可执行代码,但该进程和所有线程将保持活动状态,而其他线程将继续执行. 否则,它们将以main结尾. 对于正常退出,除非希望获取返回值,否则可以避免调用pthread_exit(). 程序员可以选择指定终止状态. 当任何线程加入该线程时,状态将返回到加入该线程的线程. pthread_exit()函数不会关闭文件. 程中打开的任何文件将保持打开状态,直到线程结束.

现在,我们使用多线程使程序能够在睡眠期间执行其他操作.

#include<cstdio>
#include<pthread.h>
#include<unistd.h>
void* printhello(void*)
{
    for(int i=1;i<=4;i++)
    {
        sleep(1);
        printf("hello! %d sec has past\n",i);
    }
}
int main()
{
    pthread_t tid;
    pthread_create(&tid,NULL,printhello,NULL);
    sleep(5);
    printf("program exited.\n");
}

该程序使用多线程,可以在主要功能进入睡眠状态时输出.

如果我们在main中使用pthread_exit()退出

#include<cstdio>
#include<pthread.h>
#include<unistd.h>
void* printhello(void*)
{
    for(int i=1;i<=4;i++)
    {
        sleep(1);
        printf("hello! %d sec has past\n",i);
    }
}
int main()
{
    pthread_t tid;
    pthread_create(&tid,NULL,printhello,NULL);
    pthread_exit(NULL);  //退出main的线程
    printf("program exited.\n");  //这段代码将不被执行
}

如果您愿意,您会发现子线程仍然可以继续执行

    pthread_exit(NULL);  //退出main的线程

更改为

    return 0;

程序将直接终止而不显示输出.

pthread_create()函数允许程序员将参数传递给线程的start_rtn函数. 当需要传递多个参数时,可以定义一个包含要传递的所有参数的结构,然后使用pthread_create()传递一个指向该结构的指针,以突破传递的参数数量的限制. 所有参数都应按引用传递并转换为(void *).

linux的进程与线程_linux多线程服务器设计_linux 进程与线程

要安全地将数据传输到新创建的线程,请确保传输的数据是线程安全的(不能被其他线程修改).

以下代码段演示了如何将简单的整数传递给线程.

#include<cstdio>
#include<pthread.h>
#include<unistd.h>
void* printid(void* id)
{
    printf("my thread id is %d\n",*(int*)id);
}
int main()
{
    pthread_t tid;
    pthread_create(&tid,NULL,printid,(void*)tid);
    pthread_exit(NULL);//不使用return是因为主函数退出太快以至于子线程没输出就被终止了
}

以下代码段演示了如何将结构参数传递给线程.

#include<cstdio>
#include<pthread.h>
#include<unistd.h>
struct point
{
    int x,y;
};
void* print(void* p)
{
    printf("I got a point (%d,%d).\n",((point*)p)->x,((point*)p)->y);
}
int main()
{
    pthread_t tid[10];
    point p[10];
    for(int i=0;i<10;i++)
    {
        p[i].x=p[i].y=i;
        pthread_create(&tid[i],NULL,print,(void*)&p[i]);
    }
    pthread_exit(NULL);
}

以下代码是错误的,该循环将导致线程在访问传递给该线程的地址之前更改参数的值,并且输出将相同.

#include<cstdio>
#include<pthread.h>
#include<unistd.h>
void* print(void* i)
{
    printf("i got a number %d\n",*(int*)i);
}
int main()
{
    pthread_t tid[10];
    for(int i=0;i<10;i++)
    {
        pthread_create(&tid[i],NULL,print,(void*)&i);
    }
    pthread_exit(NULL);
}


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-241587-1.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...