Linux 多线程

线程的优点:

  • 减少系统调度开销,不占有独立的资源,切换速度快,执行效率高。
  • 线程间通信方便,可共享资源。
  • 改善程序设计结构,功能复杂的进程可以分为多个独立的线程分别执行,模块性更强。

   线程分为:用户态线程和核心态线程。

  用户态的多线程程序在运行时不许要特定的内核支持,同一个进程的线程之间进行切换时,不需要调用系统调用。

  核心态线程的实现方法允许不同进程中的的线程按照相同的调度方法进行调度,有利于发挥多处理器的并发优势。

 

线程创建:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*),void *arg);
//thread            指向线程标识符的指针,使用这个标识符来引用新线程
//attr              设置线程属性,设为NULL则生成默认属性的线程
//start_routine     线程运行函数的起始位置
//arg               线程运行函数的参数

线程终止:

1.通过线程自身结束

void pthread_exit(void *rval_ptr);
//rval_ptr是函数的返回代码,相当于线程的退出码

2.通过同一进程的其他线程来结束

int pthread_cancel(pthread_t tid);
//tid是要结束线程的标识符

下面的函数用于阻塞等待一个线程的结束。

int pthread_join(pthread_t thread, void **return_ptr)

例子:

//创建线程,输出当前系统的时间

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<unistd.h>
#include<pthread.h>

void print_currentTime(void)
{
    time_t ct;
    ct=time(NULL);
    //ctime:将秒数转换成字符串
    printf("current time is : '%s'",ctime(&ct));
    pthread_exit("Time thread finished!\n");
}

int main()
{
    int ret;
    void *thread_result;
    pthread_t new_thread;

    ret=pthread_create(&new_thread,NULL,(void*)print_currentTime,NULL);
    if(ret!=0){
        perror("thread creation failed!\n");
        exit(EXIT_FAILURE);
    }

    printf("waiting for new thread....\n");
    ret=pthread_join(new_thread,&thread_result);
    if(ret!=0){
        perror("thread join failed!\n");
        exit(EXIT_FAILURE);
    }

    printf("thread joined, returned: %s\n",(char*)thread_result);
    return 0;
}
//编译时候注意: gcc thread_date.c -o thread_date -lpthread

 

线程属性:

线程属性主要包括分离属性,绑定属性,调度属性,堆栈属性,继承属性等,结构为pthread_attr_t。

属性设置函数:

int pthread_attr_init(pthread_attr_t *attr)
//attr是指向属性结构的指针
//注意:此函数必须在调用pthread_creater()函数之前调用

这里提到了一个概念“轻进程(Light Weight Process, LWP)”,位于用户层与系统层之间的内核线程。系统对线程资源的分配以及对线程的控制是通过轻进程来实现的,一个轻进程可以控制一个或多个线程。

获取线程绑定状态函数:

int pthread_attr_getscope(pthread_attr_t *attr, int *scope)
//scope返回绑定属性的状态

设置线程绑定属性函数: 

int pthread_attr_setscope(pthread_attr_t* attr, int scope)
//scope是要绑定的类型

获得线程优先级函数:

int pthread_attr_getschedparam(pthread_attr_t *attr, const struct sched_param *param)
//param中存放线程的调度参数信息

设置线程优先级函数:

int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param)

获取调度策略函数:

int pthread_attr_getschedpolicy(pthread_attr *attr, int *policy)
//调度策略存放在policy中

设置调度策略函数:

int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)

获取并发级别函数:

int pthread_getconcurrency(void)

设置并发级别函数:

int pthread_setconcurrency(int new_level)

 

多线程同步技术:

线程同步机制主要有:互斥量,信号量,条件变量,读写锁等。

互斥量:

数据类型为pthread_mytex_t,主要函数:

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
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);
//mutex是定义的pthread_mutex_t的指针,mutex_attr是互斥量的属性结构

例子:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<string.h>

pthread_mutex_t mutex;
int count=0;
char msg_buf[64];

void setMsg_Func(void)
{
    while(count>0){
        pthread_mutex_lock(&mutex);
        memset(msg_buf,0,64);
        sprintf(msg_buf,"count=%d.\n",count--);
        pthread_mutex_unlock(&mutex);
        srand((int)time(0));
        sleep(rand()%3);
    }
    pthread_exit(0);
}

void printMsg_Func(void)
{
    while(count>=0){
        pthread_mutex_lock(&mutex);
        printf("%s",msg_buf);
        pthread_mutex_unlock(&mutex);
        if(0==count)
            break;
        srand((int)time(0));
        sleep(rand()%3);
    }
}

int main()
{
    int ret;
    pthread_t set_thread;
    count=4;
    pthread_mutex_init(&mutex,NULL);
    ret=pthread_create(&set_thread,NULL,(void*)&setMsg_Func,NULL);
    if(ret!=0){
        perror("thread creation failed!\n");
        exit(EXIT_FAILURE);
    }

    printMsg_Func();
    ret=pthread_join(set_thread,NULL);
    if(ret!=0){
        perror("thread creation failed!\n");
        exit(EXIT_FAILURE);
    }
    printf("Finished!\n");
    pthread_mutex_destroy(&mutex);
    return 0;
}

 但是要注意,如果使用互斥量过程中,如果两个线程试图同时占用两个资源,并锁定,可能造成死锁。

条件变量:

  只使用互斥量很可能造成死锁,为此可以加入条件变量。条件变量允许线程阻塞和等待另一个线程发送信号,使用条件变量可以以原子方式阻塞线程,直到满足某个条件为止。

  互斥量主要用来保证对临界区的互斥进入,而条件变量则用于线程的阻塞等待。

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);     //创建条件变量
int pthread_cond_signal(pthread_cond_t *cond);                                  //用来释放被阻塞在条件变量cond上的进程
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);            //使线程阻塞
int pthread_cond_broadcast(pthread_cond_t *cond);                               //用来唤醒所有阻塞在条件变量cond上的线程
int pthread_cond_timewait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);//使线程阻塞,与wait不同,它经过abstime时间后,无论条件是否满足,都会释放
int pthread_cond_destroy(pthread_cond_t *cond);

//cond是一个指向结构pthread_cond_t的指针
//cond_attr是条件变量的属性结构指针

例子:

//创建两个线程,偶数时进程1给变量加1,奇数时进程2给变量加1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#define MAX_COUNT 9

pthread_mutex_t mutex;
pthread_cond_t cond;
int count=0;

void addCount_odd_Func(void)
{
    pthread_mutex_lock(&mutex);
    while(count<MAX_COUNT){
        if(count%2==1){
            count++;
            printf("addcout_odd_Func():count=%d.\n",count);
            pthread_cond_signal(&cond);
        }
        else
            pthread_cond_wait(&cond,&mutex);
    }
    pthread_mutex_unlock(&mutex);
}

void addCount_even_Func(void)
{
    pthread_mutex_lock(&mutex);
    while(count<MAX_COUNT){
        if(count%2==0){
            count++;
            printf("addCount_even_Func:count=%d.\n",count);
            pthread_cond_signal(&cond);
        }
        else
            pthread_cond_wait(&cond,&mutex);
    }
    pthread_mutex_unlock(&mutex);
}

int main(int argc, char **argv)
{
    int ret;
    pthread_t odd_thread,even_thread;
    pthread_attr_t thread_attr;
    count=0;

    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond,NULL);
    ret=pthread_attr_init(&thread_attr);
    if(ret!=0){
        perror("attribute creation failed!");
        exit(EXIT_FAILURE);
    }

    pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED);

    ret=pthread_create(&odd_thread,&thread_attr,(void*)&addCount_odd_Func,NULL);
    if(ret!=0){
        perror("thread creation failed!");
        exit(EXIT_FAILURE);
    }

    ret=pthread_create(&even_thread,&thread_attr,(void*)&addCount_even_Func,NULL);
    if(ret!=0){
        perror("thread creation failed!");
        exit(EXIT_FAILURE);
    }

    while(count<MAX_COUNT);

    printf("Finished!");
    pthread_cond_destroy(&cond);
    pthread_mutex_destroy(&mutex);

    return 0;
}

 


本文 由 cococo点点 创作,采用 知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆 许可协议进行许可。欢迎转载,请注明出处:
转载自:cococo点点 http://www.cnblogs.com/coder2012

时间: 2024-09-20 06:16:22

Linux 多线程的相关文章

Linux多线程之同步

引言 条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待条件变量的条件成立而挂起(此时不再占用cpu):另一个线程使条件成立(给出条件成立信号).为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起. 函数原型 1. 定义条件变量 #include <pthread.h>/* 定义两个条件变量 */pthread_cond_t cond_pro, cond_con; 2. 初始化和销毁条件变量 #include <pthread.h>int pt

Linux多线程的实现代码

#include <pthread.h>#include <stdio.h>#include <sys/time.h>#include <string.h>#define MAX 10pthread_t thread[2];pthread_mutex_t mut;int number=0, i;void *thread1(){ printf ("thread1 : I'm thread 1\n"); for (i = 0; i <

linux多线程编程详解教程

 这篇文章主要介绍了linux多线程编程详解教程,提供线程通过信号量实现通信的代码,大家参考使用吧 线程分类   线程按照其调度者可以分为用户级线程和核心级线程两种.   (1)用户级线程  用户级线程主要解决的是上下文切换的问题,它的调度算法和调度过程全部由用户自行选择决定,在运行时不需要特定的内核支持.在这里,操作系统往往会提供一个用户空间的线程库,该线程库提供了线程的创建.调度.撤销等功能,而内核仍然仅对进程进行管理.如果一个进程中的某一个线程调用了一个阻塞的系统调用,那么该进程包括该进程

select-ARM9 + Linux多线程精确的定时器

问题描述 ARM9 + Linux多线程精确的定时器 最近公司有个项目平台是ARM9 + linux, 在开发过程中遇到一个问题: 有一部分CAN通讯,需要250ms定时发送一帧数据包.于是我用select做了一个定时器发送.但是当这个多线程的程序真正跑起来,在接受端进行检测.结果收到的该帧的时间间隔竟然是330ms左右.虽然预先我知道有偏差,但是330的时间间隔确实大大超出了预期!如果用setitimer的话,一是资源少,二是信号如果加入程序中,可能会带来很多不必要的BUG.哪位大神有更好的定

Linux多线程编程小结

前一段时间由于开题的事情一直耽搁了我搞Linux的进度,搞的我之前学的东西都遗忘了,非常烦躁的说,如今抽个时间把之前所学的做个小节.文章内容主要总结于<Linux程序设计第3版>. 1.Linux进程与线程 Linux进程创建一个新线程时,线程将拥有自己的栈(由于线程有自己的局部变量),但与它的创建者共享全局变量.文件描写叙述符.信号句柄和当前文件夹状态. Linux通过fork创建子进程与创建线程之间是有差别的:fork创建出该进程的一份拷贝,这个新进程拥有自己的变量和自己的PID,它的时间

linux多线程编程中如何等待过个线程退出

问题描述 linux多线程编程中如何等待过个线程退出 linux多线程编程中,如果线程A创建了线程B,我知道用pthread__ join可以令线程A 阻塞然后等待线程B的退出.如果线程A创建了三个线程B,C,D,执行完的先后顺序不知.想让A必须等待三个线程都退出后再退出,应该怎么做? 连用pthread__join三次吗???但是第一次用了pthread__join后,A不就阻塞了吗? 解决方案 多线程编程(一):线程创建和退出Linux多线程编程(创建线程)Linux多线程编程(创建线程)

Linux多线程使用互斥量同步线程_Linux

本文将会给出互斥量的详细解说,并用一个互斥量解决上一篇文章中,要使用两个信号量才能解决的只有子线程结束了对输入的处理和统计后,主线程才能继续执行的问题. 一.什么是互斥量 互斥量是另一种用于多线程中的同步访问方法,它允许程序锁住某个对象,使得每次只能有一个线程访问它.为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁. 二.互斥量的函数的使用 它们的定义与使用信号量的函数非常相似,它们的定义如下: #include <pthread.h> int pthre

详解Linux多线程使用信号量同步_Linux

信号量.同步这些名词在进程间通信时就已经说过,在这里它们的意思是相同的,只不过是同步的对象不同而已.但是下面介绍的信号量的接口是用于线程的信号量,注意不要跟用于进程间通信的信号量混淆. 一.什么是信号量 线程的信号量与进程间通信中使用的信号量的概念是一样,它是一种特殊的变量,它可以被增加或减少,但对其的关键访问被保证是原子操作.如果一个程序中有多个线程试图改变一个信号量的值,系统将保证所有的操作都将依次进行. 而只有0和1两种取值的信号量叫做二进制信号量,在这里将重点介绍.而信号量一般常用于保护

Linux多线程编程(一)_Linux

一.什么是线程?       线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. 二.什么时候使用多线程?     当多个任务可以并行执行时,可以为每个任务启动一个线程. 三.线程的创建     使用pthread_create函数.     #include<pthread.h> int pthre

linux多线程编程(五)_Linux

线程 线程是计算机中独立运行的最小单位,运行时占用很少的系统资源.可以把线程看成是操作系统分配CPU时间的基本单元.一个进程可以拥有一个至多个线程.它线程在进程内部共享地址空间.打开的文件描述符等资源.同时线程也有其私有的数据信息,包括:线程号.寄存器(程序计数器和堆栈指针).堆栈.信号掩码.优先级.线程私有存储空间. 为什么有了进程的概念后,还要再引入线程呢?使用多线程到底有哪些好处?什么的系统应该选用多线程? 使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式.