`
jakielong
  • 浏览: 228512 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Linux下C语言的多线程编程学习

阅读更多

Linux下C语言的多线程编程学习
一、首先,简单了解一下多线程,从耳熟能详的fork()、pthread中理点头绪出来,然后自己写一个简单的来增加一下信心。

1、Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连 接时需要使用库libpthread.a。因此,后面的编译必须在选项中加入 -lpthread 选项,否则提示找不到pthread_create()这些函数。

2、pthread_t 是一个线程的标识符,创建线程用pthread_create(),等待线程结束用pthread_join(),这样,差不多就可以开始写第一个简单的多线程程序了,简单得类似HelloWorld

下面的是我自己写的一个最简单的程序。

#include <stdio.h>
#include <pthread.h>

 void thread()
 {
     int i;
     for (i=0;i<3;i++)
     {
         printf("This is thread %d .\r\n",i);
         sleep(i);
     }
 }
 
 int main()
 {
     pthread_t id;
     int i,ret;
     ret = pthread_create(&id,NULL,(void *)thread,NULL);
     if (ret != 0)
     {
         printf("Create thread error!\r\n");
         exit(1);
     }
     for (i=0;i<3;i++)
     {
         printf("This is the main thread %d .\r\n",i);
         sleep(i);
    }
    pthread_join(id,NULL);
    return(0);
 }

 

结果:

This is thread 0 .
This is thread 1 .
This is the main thread 0 .
This is the main thread 1 .
This is thread 2 .
This is the main thread 2 .

########################

#######绑定轻进程#######

########################


关于线程的绑定,牵涉到另外一个概念:轻进程(LWP:Light Weight Process)。 轻进程可以理解为内核线程,它位于用户层和系统层之间。系统对线程资源的分配、对线程的控制是通过轻进程来实现的,一个轻进程可以控制一个或多个线程。默 认状况下,启动多少轻进程、哪些轻进程来控制哪些线程是由系统来控制的,这种状况即称为非绑定的。绑定状况下,则顾名思义,即某个线程固定的"绑"在一个 轻进程之上。被绑定的线程具有较高的响应速度,这是因为CPU时间片的调度是面向轻进程的,绑定的线程可以保证在需要的时候它总有一个轻进程可用。通过设 置被绑定的轻进程的优先级和调度级可以使得绑定的线程满足诸如实时反应之类的要求。

不同的机器运行结果有可能不同,是由于两个“并行”的线程抢夺处理器资源造成的。而sleep(i)是我自作聪明的想法,仅

仅是为了让结果看上去更加能体现两个线程是“并行”执行的,其实完全可以省去。

线程属性:是否绑定、是否分离、堆栈地址、堆栈大小、优先级

默认的属性:非绑定、非分离、缺省1M的堆栈、与父进程同样级别的优先级。

#include <pthread.h>

pthread_attr_t attr;

pthread_t tid;


/*初始化属性值,均设为默认值*/

pthread_attr_init(&attr);

pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

/*PTHREAD_SCOPE_SYSTEM(绑定的) PTHREAD_SCOPE_PROCESS(非绑定的)*/


pthread_create(&tid, &attr, (void *) my_function, NULL);



 

########################

######设置分离状态######

########################


线程的分离状态决定一个线程以什么样的方式来终止自己。线程的默认属性下,即为非分离状态,这种情况下,原有的线程等待创建的线程结束。只有当 pthread_join()函数返回时,创建的线程才算终止,才能释放自己占用的系统资源。而分离线程不是这样子的,它没有被其他的线程所等待,自己运 行结束了,线程也就终止了,马上释放系统资源。程序员应该根据自己的需要,选择适当的分离状态。设置线程分离状态的函数为 pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)。第二个参数可选为PTHREAD_CREATE_DETACHED(分离线程)和 PTHREAD _CREATE_JOINABLE(非分离线程)。这里要注意的一点是,如果设置一个线程为分离线程,而这个线程运行又非常快,它很可能在 pthread_create函数返回之前就终止了,它终止以后就可能将线程号和系统资源移交给其他的线程使用,这样调用pthread_create的 线程就得到了错误的线程号。要避免这种情况可以采取一定的同步措施,最简单的方法之一是可以在被创建的线程里调用 pthread_cond_timewait函数,让这个线程等待一会儿,留出足够的时间让函数pthread_create返回。设置一段等待时间,是 在多线程编程里常用的方法。但是注意不要使用诸如wait()之类的函数,它们是使整个进程睡眠,并不能解决线程同步的问题。

########################

#######设置优先级#######

########################

  另外一个可能常用的属性是线程的优先级,它存放在结构sched_param中。用函数pthread_attr_getschedparam 和函数pthread_attr_setschedparam进行存放,一般说来,我们总是先取优先级,对取得的值修改后再存放回去。下面即是一段简单的 例子。

#include <pthread.h>
#include <sched.h>
pthread_attr_t attr;
pthread_t tid;
sched_param param;
int newprio=20;

pthread_attr_init(&attr);
pthread_attr_getschedparam(&attr, &param);
param.sched_priority=newprio;
pthread_attr_setschedparam(&attr, &param);
pthread_create(&tid, &attr, (void *)myfunction, myarg);

 

About Mutex

mutex是一个互斥锁对象,互斥锁是为了防止多线程同时修改某一公共资源,我在下面的程序里把它“锁”在了一个叫buffer[10]的缓冲区 上,模型是2个Reader和2个Writer,Reader要等到叫buffer的书架上有书的时候才可以read,而Writer也必须在书架没有放 满的情况下才可以把新写的书放到书架上。我的程序里书架的大小是1,当然也可以设置书架的大小,不过实现过程大同小异。就不多说了。来看程序:

#include <stdio.h>
#include <pthread.h>

void reader_function(void);
void writer_function(void);

char buffer[10]={0};
int buffer_has_item=0;
pthread_mutex_t mutex;
 
 int main(void)
 {
     pthread_t reader;

    /* 用默认属性初始化一个互斥锁对象*/
     pthread_mutex_init (&mutex,NULL);
     pthread_create(&reader,NULL, (void *)reader_function, NULL);
     writer_function();
 }

 void writer_function(void)
 {
    int i,ti;
 
     for(i=1;i<3;)
     {
         ti=i;
        /* 锁定互斥锁*/
         pthread_mutex_lock(&mutex);
         printf("Writer %d Locked Buffer.\r\n",i);
         if (buffer_has_item==0)
        {
             buffer_has_item=1;
            strcpy(buffer,"Full");
            printf("++Writer %d fill the buffer with context \"%s\".\r\n",i,buffer);
            i++;
         }
         /* 打开互斥锁*/
         printf("Writer %d Unlocked Buffer.\r\n\n\n",ti);
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
 
 }

void reader_function(void)
 {
     int i,ti;
     for(i=1;i<3;)
     {
         ti=i;
         pthread_mutex_lock(&mutex);
         printf("Reader %d Locked Buffer.\r\n",i);
         if(buffer_has_item==1)
         {
             buffer_has_item=0;
             strcpy(buffer,"Empty");
            printf("--Reader %d clean the buffer with context \"%s\".\r\n",i,buffer);
             i++;
         }
         printf("Reader %d Unlocked Buffer.\r\n\n\n",ti);
         pthread_mutex_unlock(&mutex);
         sleep(1);
     }

 }

 

结果:
Reader 1 Locked Buffer.
Reader 1 Unlocked Buffer.


Writer 1 Locked Buffer.
++Writer 1 fill the buffer with context "Full".
Writer 1 Unlocked Buffer.


Writer 2 Locked Buffer.
Writer 2 Unlocked Buffer.


Reader 1 Locked Buffer.
--Reader 1 clean the buffer with context "Empty".
Reader 1 Unlocked Buffer.


Writer 2 Locked Buffer.
++Writer 2 fill the buffer with context "Full".
Writer 2 Unlocked Buffer.


Reader 2 Locked Buffer.
--Reader 2 clean the buffer with context "Empty".
Reader 2 Unlocked Buffer.

注意,这次用到的sleep()不再是为了让结果好看, 而是为了防止一个线程始终占用资源,很多网上的教程使用的是pthread_delay_np(&delay);这个语句,不过这个似乎只能在 solaris系统上用,linux还是用sleep()和usleep()好了,有高人说可能会使该线程所在的进程都sleep,我使用下来似乎没有发 现。而且似乎linux下本来就是一个进程里只有一个线程,忘记哪个手册上说的,也许是以前的版本,不追究了,能用就行。

还 有就是在reader()和writer()里,我用了很奇怪的 i 和 ti 两个变量来对reader和writer编号,主要目的是为了保证每个Reader和Writer都能完成自己的使命,如果按照常规写法,使用for(i =1;i<3;i++)这样控制循环会使有的Reader或者Writer不能取到或者放上书。似乎说得自己都迷糊了,举例说,Reader1去取 书,恰巧这时候书架上是空的,为了保证Reader1能取到书,我就让Reader们排队,直到Reader1取到以后才轮到Reader2,对于 Writer们也实行排队.

 

转自:http://hi.baidu.com/skyeye_zeus/blog/item/35fdc8a7d93de79dd143588b.html

分享到:
评论

相关推荐

    Linux下C语言多线程编程实例

    Linux 下 C 语言多线程编程实例 Linux 下的多线程编程是一种非常重要的技术,在实际应用中有非常广泛的应用范围。多线程编程可以大大提高程序的执行效率和响应速度。但是,多线程编程也存在一些复杂性,例如线程...

    linux下C语言多线程编程实例

    在Linux环境下进行C语言多线程编程,可以利用POSIX线程库,也称为pthread库。这个库提供了创建、同步和管理线程的一系列接口,使得开发者能够在单个进程中同时执行多个任务,从而提高程序的并行性。下面将详细探讨多...

    linux下C语言多线程编程实例.pdf

    linux下C语言多线程编程实例.pdf

    Linux下的C语言多线程编程[汇编].pdf

    Linux下的C语言多线程编程 Linux下的C语言多线程编程是指在Linux操作系统中使用C语言编写多线程程序的技术。多线程编程是一种非常"节俭"的多任务操作方式,相比进程,它具有启动速度快、空间占用小、线程间通信...

    linux下C语言多线程编程实例[归纳].pdf

    linux下C语言多线程编程实例[归纳].pdf

    linux下C语言多线程编程实例.docx

    在Linux环境下进行C语言多线程编程,可以利用POSIX线程库pthread,它提供了创建、同步和管理线程的功能。以下将详细讲解本实例中涉及的多线程编程概念和关键技术。 首先,多线程是指在一个进程中创建多个执行线程,...

    C语言多线程编程实例.pdf

    标题中的“C语言多线程编程实例”直接指出了文档的主题内容,即围绕C语言编程中多线程编程技术的实例讲解。多线程是编程中的一项关键技术,能够允许程序同时执行多个线程,提高程序的运行效率和响应速度。 描述部分...

    Linux下的C语言多线程编程.doc

    "Linux下的C语言多线程编程" 本文档主要介绍了Linux下的C语言多线程编程,包括多线程的概念、优点、实现方法和实例代码。多线程技术可以提高应用程序的响应速度、使多CPU系统更加有效、改善程序结构等。 多线程的...

    Linux下C语言应用编程

    Linux下C语言应用编程》深入浅出地讲解了Linux下C应用程序开发所需的基本工具、知识和技巧,主要包括:开发工具的使用和技巧、文件I/O编程、多进程编程、进程间通信、多线程编程、网络编程等内容。可以让读者轻松、...

    linux下c语言多线程网页爬虫源代码

    综上所述,"linux下c语言多线程网页爬虫源代码"这个项目涵盖了Linux环境下的C语言编程、网络编程、多线程技术以及网页爬虫的设计和实现。在实际操作中,开发者需要深入理解这些知识点,并结合具体需求来优化爬虫的...

    linux下C语言多线程编程实例.doc

    在Linux环境下,C语言多线程编程是一种常见的并发处理方式,它允许程序同时执行多个任务,提高系统资源利用率和程序执行效率。本文将通过一个简单的实例来介绍如何在Linux下使用C语言进行多线程编程。 首先,我们要...

    Linux多线程 C语言编程关于多线程

    本文介绍了在Linux环境下进行多进程和多线程编程的基础知识。多进程编程主要涉及fork()函数的使用,而多线程编程则基于pthread线程库。通过理解这些基础知识,开发人员能够更好地利用现代操作系统提供的并发能力,...

    Linux下的C语言多线程编程

    使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空 间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种...

    linux下c语言实现多线程web服务器

    在Linux环境下,C语言是一种...综上所述,"linux下c语言实现多线程web服务器"项目涵盖了操作系统、网络编程、线程管理、内存操作、并发控制等多个方面,对于理解系统级编程和Web服务的内部工作原理有着重要的实践价值。

    Linux下C语言编程--线程操作

    ### Linux下C语言编程——线程操作 #### 前言:Linux下线程的创建与基础使用 ...以上内容涵盖了在Linux环境下使用C语言进行线程编程的基础知识及示例。对于更深入的理解和应用,建议进一步研究相关的文档和资料。

Global site tag (gtag.js) - Google Analytics