linux学习笔记-读《Linux编程技术详解》(12)-Linux 系统下的多线程

来源:互联网 发布:软件生存周期阶段 编辑:程序博客网 时间:2024/06/16 01:25

线程,也被称为轻量进程,指的是进程中某个单一顺序的控制流。线程是进程中的实体,一个进程可以拥有多个线程,而一个线程必须有一个父进程。线程与父进程的其他线程一起共享进程的所有资源。线程本身不拥有系统资源,只是拥有一些运行必须的数据结构而已。进程是资源管理的最小单位,而线程是程序执行的最小单位。

根据线程的调度者是位于系统内核中还是位于系统内核外,线程可以划分为内核态线程和用户态线程两大类。

1.         内核态线程

该线程由内核调度程序直接调度,在核心态下可以充分发挥多处理机的优势。目前,Linux系统的标准线程库就是采用内核线程方式实现多线程。内核线程可以充分发挥多处理器的性能。

2.         用户态线程

一个进程可以包含几个线程。这些线程从内核调度程序的视角来看只是一个进程,内核将他们作为一个进程来调度。线程之间的调度是在用户态下进行的。实际上,线程对于内核调度程序而言是不可见的。用户线程的优点是调度的高效性;缺点是在多处理器上性能不高,一个线程的系统调用阻塞将导致整个线程组阻塞。

目前,线程主要的实现方法是用户态线程。与内核态线程不同,用户态线程在线程切换时不需要调用系统调用。因此,资源消耗较少,有利于实现一个进程启动多个线程的场合。同时,通过修改用户态线程的实现方式可以适应特殊应用的要求,这对于多媒体实时处理尤为有利。

有资料表明,进程在系统资源方面的开销是线程的30倍左右。因此,在资源消耗上,进程与线程相比,没有任何的优势。

Linux系统中,所有与线程相关的函数都是以pthread开头的. pthread_create函数用于在当前进程中加入新的线程。

int pthread_create(pthread_t *restrict thread,

                             const pthread_attr_t *restrict attr,

                             void *(*start_routine)(void *), void *restrict arg);

UNIX不同,在Linux中,当调用pthread_create创建线程时,系统首先创建一个新的进程,再在该进程内创建需要的线程。

pthread_exit函数用于结束线程的运行。

           void pthread_exit(void *value_ptr);

为了让主线程等待创建的线程运行完成后才退出,可在main函数中调用pthread_join函数。

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

pthread_join函数将挂起调用该函数的线程,直到thread参数指定的线程运行结束。

 

线程属性

           int pthread_attr_init(pthread_attr_t *attr);

pthread_attr_init 函数用于使用参数attr中的属性来初始化线程属性对象。该函数必须在pthread_create函数之前调用。

线程的分离状态将决定线程如何结束。默认情况下,创建出的线程是处于非分离状态的,这种线程在进程没有退出之前,不会释放线程所占用的资源。非分离线程可以通过调用pthread_join函数来等待其他线程结束。这样线程在结束之后会释放自己占用的资源。处于分离状态的线程会在线程退出时释放所占用的资源。

 

           int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

此函数设置线程属性对象的线程分离状态。

 

           int pthread_attr_getdetachstate(const pthread_attr_t *attr,

                                                int *detachstate);

此函数从attr参数中获得线程分离状态信息。

 

           int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope);

           int pthread_attr_getscope(const pthread_attr_t *attr,

                                                int *restrict contentionscope);

这两个函数用于设置或获得线程属性对象的作用域。作用域用于控制线程是在进程内还是在系统所有进程间进行调度。

 

线程同步

多进程对共享资源进行访问的时候,必须保证某个时刻只有一个进程访问资源,这个问题在多线程情况下,同样是存在的。为此,Linux系统提供了互斥锁来保证某个时刻只有一个线程使用资源。

互斥锁提供了在多线程情况下相互排斥的方法。

互斥锁

互斥锁的锁定和解锁是通过pthread_mutex_lock函数和pthread_mutex_unlock函数来实现的。互斥锁一般用来保护数据结构。通过线程对互斥锁的锁定和解锁,能够实现某一时刻只有一个线程访问数据结构。

互斥锁操作主要有三种行为,分别是加锁、解锁和测试加锁。当对互斥锁进行了加锁操作,在没有进行解锁之前,任何线程都没有办法获得互斥锁。

创建互斥锁可通过两种途径来实现:

1、 通过POSIX标准中定义的宏来实现对互斥锁的初始化,

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

2、 调用pthread_mutex_init函数实现互斥锁的初始化,

int pthread_mutex_init(pthread_mutex_t *restrict mutex,

                               const pthread_mutexattr_t *restrict attr);

使用PTHREAD_MUTEX_INITIALIZER宏来初始化互斥锁,其效果等同于调用pthread_mutex_init函数时将attr参数指定为NULL

 

pthread_mutex_lock函数用于对互斥锁进行加锁操作:

           int pthread_mutex_lock(pthread_mutex_t *mutex)

phtread_mutex_trylock函数与pthread_mutex_lock函数功能类似 ,同样用于实现对互斥锁的加锁操作。

           int pthread_mutex_trylock(pthread_mutex_t *mutex);

具体不同参考man manual;

           int pthread_mutex_unlock(pthread_mutex_t *mutex);

此函数将释放参数mutex中指向的互斥锁,释放类型依赖于互斥锁的锁类型。

原创粉丝点击