首页 > 代码库 > Linux多线程实践(2) --线程基本API

Linux多线程实践(2) --线程基本API

POSIX线程库

与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”打头,要使用这些函数库,要通过引入头文<pthread.h>,而且链接这些线程函数库时要使用编译器命令的“-lpthread”选项[Ubuntu系列系统需要添加的是”-pthread”选项而不是”-lpthread”,如Ubuntu 14.04版本,深度Ubuntu等]

 

pthread_create

创建一个新的线程

       int pthread_create(pthread_t *restrict thread,
              const pthread_attr_t *restrict attr,
              void *(*start_routine)(void*), void *restrict arg);

参数:

thread:线程ID

attr:设置线程的属性,attr为NULL表示使用默认属性

start_routine:是个函数地址,线程启动后要执行的函数

arg:传给线程启动函数的参数

返回值:成功返回0;失败返回错误码

 

附-错误检查

UNIX传统的函数:成功返回0,失败返回-1,并且对设置全局变量errno以指定错误类型。然而pthreads函数出错时不会设置全局变量errno(而其他的大部分POSIX函数会设置errno)。而是将错误代码通过返回值返回;

pthreads同样也提供了线程内的errno变量,以支持其它使用errno的代码。对于pthreads函数的错误,建议通过返回值进行判定,因为读取返回值要比读取线程内的errno变量的开销更小!

//实践
#include <iostream>

#include <errno.h>
#include <unistd.h>
#include <pthread.h>

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

void *thread_routine(void *args)
{
    for (int i = 0; i < 20; ++i)
    {
        printf("A");
        fflush(stdout);
        usleep(20);
    }
    return 0;
}

int main()
{
    pthread_t tid;
    int ret = 0;
    if ((ret = pthread_create(&tid,NULL, thread_routine,NULL),NULL) != 0)
    {
        fprintf(stderr,"%s\n",strerror(ret));
        exit(-1);
    }

    for (int i = 0; i < 20; ++i)
    {
        printf("B");
        fflush(stdout);
        usleep(20);
    }

    cout << endl;

    pthread_join(tid,NULL);	//该函数下面会遇到:等待线程结束
}


运行结果(可以发现线程是交替运行的,并且运行情况不一):

技术分享

pthread_exit

线程终止

 void pthread_exit(void *value_ptr);

参数:

value_ptr:指向该线程的返回值;注意:value_ptr不能指向一个局部变量

 

 

pthread_join

等待线程结束

int pthread_join(pthread_t thread, void **value_ptr);

参数:

thread:线程ID

value_ptr:它指向一个指针,后者指向线程的返回值(用户获取线程的返回值)

返回值:成功返回0;失败返回错误码


//实践
void *threadFunction(void *args)
{
    cout << "Start Thread..." << endl;
    cout << "End Thread..." << endl;

    pthread_exit(NULL);
}

int main()
{
    pthread_t thread;
    //启动创建并启动线程
    pthread_create(&thread,NULL,threadFunction,NULL);

    cout << "Main Running..." << endl;
    cout << "Main Ending..." << endl;

    //等待线程结束
    pthread_join(thread,NULL);

    return 0;
}


pthread_self

返回线程ID

pthread_t pthread_self(void);
DESCRIPTION
	The pthread_self() function shall return the thread ID of the  calling thread.

//实践1:
void *thread_routine(void *args)
{
    cout << pthread_self() << " START..." << endl;
    for (int i = 0; i < 20; ++i)
    {
        printf("A");
        fflush(stdout);
        usleep(20);
    }
    sleep(3);

    cout << pthread_self() << " END..." << endl;
    pthread_exit(const_cast<char *>("thread_routine exit"));
    //return (void *)"EDF";
}

int main()
{
    pthread_t tid;
    int ret = 0;
    if ((ret = pthread_create(&tid,NULL, thread_routine,NULL),NULL) != 0)
    {
        fprintf(stderr,"pthread_create: %s\n",strerror(ret));
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < 20; ++i)
    {
        printf("B");
        fflush(stdout);
        usleep(20);
    }
    cout << endl;

    void *threadValue;
    if ((ret = pthread_join(tid,&threadValue)) != 0)
    {
        fprintf(stderr, "pthread_join: %s\n",strerror(ret));
        exit(EXIT_FAILURE);
    }
    cout << "return message: " << static_cast<char *>(threadValue) << endl;
}
技术分享

//实践2:主控线程与子线程传递数据
typedef struct _Student
{
    char name[20];
    unsigned int age;
} Student;

void *threadFunction(void *args)
{
    cout << "In Thread: " << pthread_self() << endl;
    Student tmp = *(Student *)(args);
    cout << "Name: " << tmp.name << endl;
    cout << "Age: " << tmp.age << endl;

    pthread_exit(NULL);
}

int main()
{
    Student student = {"xiaofang",22};

    pthread_t thread;
    //启动创建并启动线程
    pthread_create(&thread,NULL,threadFunction,&student);
    //等待线程结束
    pthread_join(thread,NULL);

    return 0;
}

技术分享


pthread_cancel

取消一个执行中的线程      

int pthread_cancel(pthread_t thread);

返回值:成功返回0;失败返回错误码;

 

pthread_detach

将一个线程分离-如果在新创建的线程结束时主线程没有结束同时也没有调用pthread_join,则会产生僵线程,次问题可以通过设置线程为分离的(detach)来解决;

int pthread_detach(pthread_t thread);

返回值:成功返回0;失败返回错误码;

 

总结:进程 VS. 线程

进程(pid_t)

线程(pthread_t)

Fork

Pthread_create

Waitpit

Pthread_join/Pthread_detach

Kill

Pthread_cancel

Pid

Pthead_self

Exit/return

Pthread_exit/return


Linux多线程实践(2) --线程基本API