首页 > 其他 > 详细

Linux下的线程

时间:2014-03-05 18:37:19      阅读:468      评论:0      收藏:0      [点我收藏+]

一、线程的优点

与传统进程相比,用线程来实现相同的功能有如下优点:

(1)系统资源消耗低。

(2)速度快。

(3)线程间的数据共享比进程间容易的多。

二、多线程编程简单实例

bubuko.com,布布扣
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>


void
thread1_routine(void)
{
    printf("new thread:thread_id is %u, process_id is %u\n",
         pthread_self(), getpid());
}
void
thread2_routine(void)
{
    printf("new thread:thread_id is %u, process_id is %u\n",
         pthread_self(), getpid());
}

int
main(void)
{
    pthread_t pt;
    printf("old thread:thread_id is %u, process_id is %u\n",
        pthread_self(), getpid()); 
    pthread_create(&pt, NULL, (void *)thread1_routine, NULL);
    pthread_create(&pt, NULL, (void *)thread2_routine, NULL);
    usleep(5);
    return(0);
}
bubuko.com,布布扣

运行结果如下(可以看出在同一个进程中有三个不同的线程同时在运行):

bubuko.com,布布扣

bubuko.com,布布扣

三、线程属性

bubuko.com,布布扣

线程属性包括绑定属性、分离属性、堆栈地址、堆栈大小和优先级。其中分离属性、堆栈地址以及堆栈大小的介绍可参考http://www.cnblogs.com/nufangrensheng/p/3522583.html。系统默认的是非邦定、非分离、缺省1M的堆栈、与父进程同样级别的优先级。在pthread_create中,把第二个参数设置为NULL的话,将采用默认的属性配置。

1、绑定属性

线程可以分为用户级线程和内核级线程两种(可参考http://blog.csdn.net/songjinshi/article/details/9042265以及http://www.xuebuyuan.com/1380720.html),而绑定属性正是设置用户级线程和内核级线程之间的关系。

绑定属性分为两种:绑定和非绑定。在绑定属性下,一个用户级线程固定分配给一个内核线程,因为CPU时间片的调度是面向内核线程(轻量级进程)的,因此具有 绑定属性的线程可以保证在需要的时候总有一个内核线程与之对应。在非绑定属性下,用户线程和内核线程的关系不是始终固定的,而是由系统根据实际情况分配的。

bubuko.com,布布扣

2、优先级

bubuko.com,布布扣

bubuko.com,布布扣

四、线程互斥

bubuko.com,布布扣

bubuko.com,布布扣

bubuko.com,布布扣

生产者消费者实例(多线程+互斥量):

bubuko.com,布布扣
#include <stdio.h>
#include <pthread.h>
#include <sched.h>

void *producter_f(void *arg);
void *consumer_f(void *arg);

int buffer_has_item = 0;
pthread_mutex_t mutex;
int running = 1;

int 
main(void)
{
    pthread_t consumer_t;
    pthread_t producter_t;

    pthread_mutex_init(&mutex, NULL);

    pthread_create(&producter_t, NULL, (void *)producter_f, NULL);

    pthread_create(&consumer_t, NULL, (void *)consumer_f, NULL);

    sleep(1);      /* 等待线程创建完毕 */
    running = 0;
    pthread_join(consumer_t, NULL);
    pthread_join(producter_t, NULL);
    pthread_mutex_destroy(&mutex);

    return(0);
}

void *
producter_f(void *arg)
{
    while(running)
    {
        if(buffer_has_item < 10) /* 最多允许生产10个 */
        {
            pthread_mutex_lock(&mutex);
            buffer_has_item++;
            printf("product, total: %d\n", buffer_has_item);
            pthread_mutex_unlock(&mutex);
        }
    }
}

void *
consumer_f(void *arg)
{
    while(running)
    {
        if(buffer_has_item > 0)   /* 缓冲区为空时不允许再消费 */
        {
            pthread_mutex_lock(&mutex);
            buffer_has_item--;
            printf("consume, total: %d\n", buffer_has_item);
            pthread_mutex_unlock(&mutex);
        }
    }
}
bubuko.com,布布扣

编译运行结果如下:

bubuko.com,布布扣

bubuko.com,布布扣

 

五、线程中使用信号量

(此处使用的信号量是POSIX无名信号量:http://www.cnblogs.com/nufangrensheng/p/3564306.html

线程的信号量与进程的信号量类似,使用线程的信号量可以高效地完成基于线程的资源计数。信号量实际上是一个非负的整数计数器,用来实现对公共资源的控制。在公共资源增加的时候,信号量的值增加;公共资源消耗的时候,信号量的值减少;只有当信号量的值大于0时,才能允许访问信号量所代表的公共资源。

bubuko.com,布布扣

bubuko.com,布布扣

bubuko.com,布布扣

bubuko.com,布布扣

bubuko.com,布布扣

生产者消费者实例(多线程+信号量):

bubuko.com,布布扣
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

void *producter_f(void *arg);
void *consumer_f(void *arg);

sem_t sem;
int running = 1;

int 
main(void)
{
    pthread_t consumer_t;
    pthread_t producter_t;
    
    sem_init(&sem, 0, 16);

    pthread_create(&producter_t, NULL, (void *)producter_f, NULL);

    pthread_create(&consumer_t, NULL, (void *)consumer_f, NULL);

    sleep(1);
    running = 0;
    pthread_join(consumer_t, NULL);
    pthread_join(producter_t, NULL);
    sem_destroy(&sem);

    return(0);
}

void *
producter_f(void *arg)
{
    int semval = 0;
    while(running)
    {
        usleep(1);
        sem_post(&sem);
        sem_getvalue(&sem, &semval);
        printf("product, total: %d\n", semval);
    }
}

void *
consumer_f(void *arg)
{
    int semval = 0;
    while(running)
    {
        usleep(1);
        sem_wait(&sem);
        sem_getvalue(&sem, &semval);
        printf("consume, total: %d\n", semval);
    }
}
bubuko.com,布布扣
编译运行如下:

bubuko.com,布布扣

bubuko.com,布布扣

bubuko.com,布布扣

 

更多关于线程的介绍可参考http://www.cnblogs.com/nufangrensheng/p/3518114.html及其后续博文。

Linux下的线程,布布扣,bubuko.com

Linux下的线程

原文:http://www.cnblogs.com/nufangrensheng/p/3581962.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!