Linux多线程编程指南:提高程序性能的有效手段(在linux中运用多线程知识)

随着计算机技术的飞速发展,人们对计算机性能的要求也越来越高。为了提高程序的执行效率,多线程编程成为了一个不可或缺的手段。而作为高效、稳定性极佳的操作系统之一,Linux自然也成为了多线程编程的首选平台。

十年的郫都网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。成都营销网站建设的优势是能够根据用户设备显示端的尺寸不同,自动调整郫都建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联建站从事“郫都网站设计”,“郫都网站推广”以来,每个客户项目都认真落实执行。

本文将介绍Linux多线程编程的基本思想、相关概念及实例,帮助读者掌握Linux多线程编程的核心技巧,提高程序性能,实现更为高效的计算机应用程序。

一、多线程编程的基本思想

多线程编程的基本思想是利用多线程来解决单线程执行效率低下的问题。多线程程序在执行时会分配多个线程来同时执行不同的任务,从而加速整个程序的执行速度。

多线程编程的核心思想是并发执行。在单线程程序中,代码是按照一定的顺序执行的,需要等到当前任务完成之后,才能进行下一个任务。而在多线程程序中,每个线程可以并发执行一个任务,不需要等待其他线程完成,从而更大化地利用了处理器的并行性能。

在 Linux 中,多线程编程程序是采用线程库来实现的。线程是相对轻量级的执行单元,线程的创建、管理和销毁都是由操作系统负责的,使开发人员能够针对问题的性质选择合适的并发模型,通过线程库对线程进行管理和调度,实现高效的程序执行。

二、多线程编程的相关概念

1.线程和进程

在 Linux 中,一个进程可以包含多个线程。进程是操作系统中任务的基本单位,而线程则是进程中的执行单元。每个线程拥有自己的栈、程序计数器和寄存器,以及可自行调度的优先级等信息,但不拥有独立的代码、数据和堆栈空间。

多线程程序中,通常会同时创建多个线程,每个线程都可以独立进行执行不同的任务。线程之间可以共享进程的资源,如内存空间、文件描述符等,但也需要考虑线程竞争和同步问题。

2.线程同步和互斥

在线程中,如果多个线程同时访问同一块资源(如内存),就可能会发生不可预期的情况,如数据混杂、死锁等。因此,在多线程编程中必须采用互斥和同步技术(如信号量、互斥锁、条件变量等)来解决线程之间的竞争问题,保证线程执行的正确性。

互斥是一种保证临界区内代码不被多个线程同时执行的方法。在临界区的代码中,需要加入互斥锁进行保护,当一个线程进入临界区时,会锁定互斥锁,其他线程则不能进入临界区,直到当前线程解锁互斥锁,其他线程才能继续执行临界区的代码。

同步则是通过信号量、条件变量等来实现线程之间的协作。例如,生产者线程和消费者线程之间,需要通过信号量来协调生产和消费的数量和时间,避免队列溢出和资源浪费等问题。

三、多线程编程的实例

下面通过代码示例来说明Linux下多线程编程的实现过程。

1、创建线程

在 Linux 中,线程的创建可以采用 pthread_create() 函数实现。函数原型如下:

#include

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

其中,参数说明如下:

thread:指向 pthread_t 类型数据的指针,用于存储创建后线程的 ID;

attr:线程属性,通常为 NULL;

start_routine:指向线程主函数的指针;

arg:向线程主函数传递的参数。

2、线程同步和互斥

在多线程编程中,需要考虑线程的同步和互斥,以保证程序的正确性和稳定性。例如,下面实现了一个线程安全的队列:

typedef struct {

void **items;

int max_size;

int front;

int rear;

pthread_mutex_t lock;

pthread_cond_t has_items;

pthread_cond_t has_space;

} SafeQueue;

void safe_queue_init(SafeQueue *queue, int max_items) {

queue->items = malloc(sizeof(void*) * max_items);

queue->max_size = max_items;

queue->front = 0;

queue->rear = 0;

pthread_mutex_init(&queue->lock, NULL);

pthread_cond_init(&queue->has_items, NULL);

pthread_cond_init(&queue->has_space, NULL);

}

void safe_queue_push(SafeQueue *queue, void *item) {

pthread_mutex_lock(&queue->lock);

while(queue->rear >= queue->max_size) {

pthread_cond_wt(&queue->has_space, &queue->lock);

}

queue->items[queue->rear] = item;

queue->rear++;

pthread_cond_signal(&queue->has_items);

pthread_mutex_unlock(&queue->lock);

}

void *safe_queue_pop(SafeQueue *queue) {

pthread_mutex_lock(&queue->lock);

while(queue->front == queue->rear) {

pthread_cond_wt(&queue->has_items, &queue->lock);

}

void *item = queue->items[queue->front];

queue->front++;

pthread_cond_signal(&queue->has_space);

pthread_mutex_unlock(&queue->lock);

return item;

}

在上述代码中,通过互斥锁 pthread_mutex_lock() 和信号量 pthread_cond_wt() 来保证线程的安全同步,满足生产者和消费者之间的交替需求;同时,还使用了条件变量 pthread_cond_signal() 来及时通知对应线程,避免线程出现阻塞等待的情况。

3、线程池

在多线程编程中,线程池是一种非常重要的技术,可以有效地控制线程的资源使用,并提高程序的效率。下面实现了一个线程池的例子:

typedef struct {

SafeQueue task_queue;

pthread_t *threads;

int num_threads;

int shutdown;

} ThreadPool;

void thread_pool_init(ThreadPool *pool, int num_threads) {

pool->threads = malloc(sizeof(pthread_t) * num_threads);

pool->num_threads = num_threads;

pool->shutdown = 0;

safe_queue_init(&pool->task_queue, num_threads);

for(int i = 0; i

pthread_create(&pool->threads[i], NULL, thread_pool_worker, pool);

}

}

void thread_pool_add_task(ThreadPool *pool, void (*task)(void *), void *arg) {

Task *t = malloc(sizeof(Task));

t->task_fn = task;

t->arg = arg;

safe_queue_push(&pool->task_queue, t);

}

void thread_pool_shutdown(ThreadPool *pool) {

for(int i = 0; i num_threads; i++) {

pthread_join(pool->threads[i], NULL);

}

pool->shutdown = 1;

}

void *thread_pool_worker(void *arg) {

ThreadPool *pool = (ThreadPool*) arg;

while(!pool->shutdown) {

Task *t = safe_queue_pop(&pool->task_queue);

if(t != NULL) {

t->task_fn(t->arg);

free(t);

}

}

return NULL;

}

在上述代码中,我们首先通过 SafeQueue 实现了一个线程安全的任务队列,然后通过线程池实现了任务的分发和管理。线程池包含了多个线程,每个线程都会不断地从队列中获取任务进行处理,每个任务都将被一个独立的线程执行,从而有效地发挥了计算机的并行性能。

成都网站建设公司-创新互联为您提供网站建设、网站制作、网页设计及定制高端网站建设服务!

linux 多线程环境下的几种锁机制

NO1

互斥量(Mutex)

互斥量是实现最简单的锁类型,因此有一些教科书一般以互斥量为例对锁原语进行描述。互斥量的释放并不仅仅依赖于释放操作,还可以引入一个定时器属性。如果在释放操作执行前发生定时器超时,则互斥量也会释放代码块或共享存储区供其他线程访问。当有异常发生时,可使用try-finally语句来确保互斥量被释放。定时器状态或try-finally语句的使用可以避免产生死锁。

递归锁(Recursive

Lock)

递归锁是指可以被当前持有该锁的线程重复获取,而不会导致该线程产生死锁的锁类型。对递归锁而言,只有在当前持有线程的获取锁操作都有一个释放操作与之对应时,其他线程才可以获取该锁。因此,在使用递归锁时,必须要用足够的释放锁操作来平衡获取锁操作,实现这一目标的更佳方式是在单入口单出口代码块的两头一一对应地使用获取、释放操作,做法和在普通锁中一样。递归锁在递归函数中最有用。但是,总的来说,递归锁比非递归锁速度要慢。需要注意的是:调用线程获得几次递归锁必须释放几次递归锁。

以下为一个递归锁的示例:

view plain copy

Recursive_Lock L

void recursiveFunction (int count) {

L->acquire()

if (count > 0) {

count = count – 1;

recursiveFunction(count);

}

L->release();

}

读写锁(Read-Write

lock) 读写锁又称为共享独占锁(shared-exclusive

lock)、多读单写锁(multiple-read/single-write lock)或者非互斥信号量(non-mutual

exclusion

semaphore)。读写锁允许多个线程同时进行读访问,但是在某一时刻却最多只能由一个线程执行写操作。对于多个线程需要同时读共享数据却并不一定进行写操作的应用来说,读写锁是一种高效的同步机制。对于较长的共享数据,只为其设置一个读写锁会导致较长的访问时间,更好将其划分为多个小段并设置多个读写锁以进行同步。

这个读写锁我们在学习数据库的时候应该很熟悉的哟!

旋转锁(Spin

Lock)

旋转锁是一种非阻塞锁,由某个线程独占。采用旋转锁时,等待线程并不静态地阻塞在同步点,而是必须“旋转”,不断尝试直到最终获得该锁。旋转锁多用于多处理器系统中。这是因为,如果在单核处理器中采用旋转锁,当一个线程正在“旋转”时,将没有执行资源可供另一释放锁的线程使用。旋转锁适合于任何锁持有时间少于将一个线程阻塞和唤醒所需时间的场合。线程控制的变更,包括线程上下文的切换和线程数据结构的更新,可能比旋转锁需要更多的指令周期。旋转锁的持有时间应该限制在线程上下文切换时间的50%到100%之间(Kleiman,1996年)。在线程调用其他子系统时,线程不应持有旋转锁。对旋转锁的不当使用可能会导致线程饿死,因此需谨慎使用这种锁机制。旋转锁导致的饿死问题可使用排队技术来解决,即每个等待线程按照先进先出的顺序或者队列结构在一个独立的局部标识上进行旋转。

浅谈linux 多线程编程和 windows 多线程编程的异同

很早以前就想写写linux下多线程编程和windows下的多线程编程了,但是每当写时又不知道从哪个地方写起,怎样把自己知道的东西都写出来,下面我就谈世罩让谈linux多线程及线程同步,并将它和windows的多线程进行比较,看看他们之间有什么相同点和不同的地方。

其实最开始我是搞windows下编程的,包括windows编程,windows 驱动,包括u驱动,ndis驱动,pci驱动,1394驱动等等,同时也一条龙服务,做windows下的应用程序开发,后面慢慢的我又对linux开发产生比较深的兴趣和爱好,就转到搞linux开发了。在接下来的我还会写一些博客,主要是写linux编程和windows编程的区别吧,现在想写的是linux下u驱动和windows下u驱动开发的区别,这些都是后话,等我将linux多线程和windows多线程讲解完后,我再写一篇u驱动,谈谈windows 和linux u驱动的东东。好了,言归正传。开始将多线程了。

首先我们讲讲为什么搜局要采用多线程编程,其实并不是所有的程序都必须采用多线程,有些时候采用多线程,性能还没有单线程好。所以我们要搞清楚,什么时候采用多线程。采用多线程的好处如下:

(1)因为多线程彼此之间采用相同的地址空间,共享大部分的数据,这样和多进程相比,代价比较节俭,因为多进程的话,启动新的进程必须分配给它独立的地址空间,这样需要数据表来维护代码段,数据段和堆栈段等等。

(2)多线程和多进程相比,一个明显的优点就是线程之间的通信了,对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。但是对于多线程就不一样了。他们之间可以直接共享数据,比如最简单的方式就是共享全局变量。但是共享全部变量也要注意哦,呵呵,必须注意同步,不然后果你知道的。呵呵。

(3)在多cpu的情况下,不同的线程可以运行不同的cpu下,这样就完全并行了。

反正我觉得在这种情况下,采用多线程比较理想。比如说你要做一个任务分2个步骤,你为提高工作效率,你可以多线程技术,开辟2个线程,之一个线程就做之一步的工作,第2个线程就做第2步的工作。但是你这个时候要注意同步了。因为只有之一步做完才能做第2步的工作。这时,我们可以采用同步技术进行线程之间的通信。

针对这种情况,我们首先讲讲多线程之间的通信,在windows平台下,多线程之间通信采用的方法主要有:

(1)共享全局变量,这种闷仔方法是最容易想到的,呵呵,那就首先讲讲吧,比如说吧,上面的问题,之一步要向第2步传递收据,我们可以之间共享全局变量,让两个线程之间传递数据,这时主要考虑的就是同步了,因为你后面的线程在对数据进行操作的时候,你之一个线程又改变了数据的内容,你不同步保护,后果很严重的。你也知道,这种情况就是读脏数据了。在这种情况下,我们最容易想到的同步方法就是设置一个bool flag了,比如说在第2个线程还没有用完数据前,之一个线程不能写入。有时在2个线程所需的时间不相同的时候,怎样达到更大效率的同步,就比较麻烦了。咱们可以多开几个缓冲区进行操作。就像生产者消费者一样了。如果是2个线程一直在跑的,由于时间不一致,缓冲区迟早会溢出的。在这种情况下就要考虑了,是不让数据写入还是让数据覆盖掉老的数据,这时候就要具体问题具体分析了。就此打住,呵呵。就是用bool变量控制同步,linux 和windows是一样的。

既然讲道了这里,就再讲讲其它同步的方法。同样 针对上面的这个问题,共享全局变量同步问题。除了采用bool变量外,最容易想到的方法就是互斥量了。呵呵,也就是传说中的加锁了。windows下加锁和linux下加锁是类似的。采用互斥量进行同步,要想进入那段代码,就先必须获得互斥量。

linux上互斥量的函数是:

windows下互斥量的函数有:createmutex 创建一个互斥量,然后就是获得互斥量waitforsingleobject函数,用完了就释放互斥量ReleaseMutex(hMutex),当减到0的时候 内核会才会释放其对象。下面是windows下与互斥的几个函数原型。

HANDLE WINAPI CreateMutex(

__in LPSECURITY_ATTRIBUTES lpMutexAttributes,

__in BOOL bInitialOwner,

__in LPCTSTR lpName

);

可以可用来创建一个有名或无名的互斥量对象

之一参数 可以指向一个结构体SECURITY_ATTRIBUTES 一般可以设为null;

第二参数 指当时的函数是不是感应感应状态 FALSE为当前拥有者不会创建互斥

第三参数 指明是否是有名的互斥对象 如果是无名 用null就好。

DWORD WINAPI WaitForSingleObject(

__in HANDLE hHandle,

__in DWORD dwMilliseconds

);

之一个是 创建的互斥对象的句柄。第二个是 表示将在多少时间之后返回 如果设为宏INFINITE 则不会返回 直到用户自己定义返回。

对于linux操作系统,互斥也是类似的,只是函数不同罢了。在linux下,和互斥相关的几个函数也要闪亮登场了。

pthread_mutex_init函数:初始化一个互斥锁;

pthread_mutex_destroy函数:注销一个互斥锁;

pthread_mutex_lock函数:加锁,如果不成功,阻塞等待;

pthread_mutex_unlock函数:解锁;

pthread_mutex_trylock函数:测试加锁,如果不成功就立即返回,错误码为EBUSY;

至于这些函数的用法,google上一搜,就出来了,呵呵,在这里不多讲了。windows下还有一个可以用来保护数据的方法,也是线程同步的方式

就是临界区了。临界区和互斥类似。它们之间的区别是,临界区速度快,但是它只能用来同步同一个进程内的多个线程。临界区的获取和释放函数如下:

EnterCriticalSection() 进入临界区; LeaveCriticalSection()离开临界区。 对于多线程共享内存的东东就讲到这里了。

(2)采用消息机制进行多线程通信和同步,windows下面的的消息机制的函数用的多的就是postmessage了。Linux下的消息机制,我用的较少,就不在这里说了,如果谁熟悉的,也告诉我,呵呵。

(3)windows下的另外一种线程通信方法就是事件和信号量了。同样针对我开始举得例子,2个线程同步,他们之间传递信息,可以采用事件(Event)或信号量(Semaphore),比如之一个线程完成生产的数据后,就必须告诉第2个线程,他已经把数据准备好了,你可以来取走了。第2个线程就把数据取走。呵呵,这里可以采用消息机制,当之一个线程准备好数据后,就直接postmessage给第2个线程,按理说采用postmessage一个线程就可以搞定这个问题了。呵呵,不是重点,省略不讲了。

对于linux,也有类似的方法,就是条件变量了,呵呵,这里windows和linux就有不同了。要特别讲讲才行。

对于windows,采用事件和信号量同步时候,都会使用waitforsingleobject进行等待的,这个函数的之一个参数是一个句柄,在这里可以是Event句柄,或Semaphore句柄,第2个参数就是等待的延迟,最终等多久,单位是ms,如果这个参数为INFINITE,那么就是无限等待了。释放信号量的函数为ReleaseSemaphore();释放事件的函数为SetEvent。当然使用这些东西都要初始化的。这里就不讲了。Msdn一搜,神马都出来了,呵呵。神马都是浮云!

对于linux操作系统,是采用条件变量来实现类似的功能的。Linux的条件变量一般都是和互斥锁一起使用的,主要的函数有:

pthread_mutex_lock ,

pthread_mutex_unlock,

pthread_cond_init

pthread_cond_signal

pthread_cond_wait

pthread_cond_timewait

为了和windows操作系统进行对比,我用以下表格进行比较:

对照以上表格,总结如下:

(1) Pthread_cleanup_push,Pthread_cleanup_pop:

这一对函数push和pop的作用是当出现异常退出时,做一些清除操作,即当在push和pop函数之间异常退出,包括调用pthread_exit退出,都会执行push里面的清除函数,如果有多个push,注意是是栈,先执行后面的那个函数,在执行前面的函数,但是注意当在这2个函数之间通过return 退出的话,执不执行push后的函数就看pop函数中的参数是不是为0了。还有当没有异常退出时,等同于在这里面return退出的情况,即:当pop函数参数不为0时,执行清除操作,当pop函数参数为0时,不执行push函数中的清除函数。

(2)linux的pthread_cond_signal和SetEvent的不同点

Pthread_cond_singal释放信号后,当没有Pthread_cond_wait,信号马上复位了,这点和SetEvent不同,SetEvent是不会复位的。详解如下:

条件变量的置位和复位有2种常用模型:之一种模型是当条件变量置位时(signaled)以后,如果当前没有线程在等待,其状态会保持为置位(signaled),直到有等待的线程进入被触发,其状态才会变为unsignaled,这种模型以采用Windows平台上的Auto-set Event 为代表。

第2种模型则是Linux平台的pthread所采用的模型,当条件变量置位(signaled)以后,即使当前没有任何线程在等待,其状态也会恢复为复位(unsignaled)状态。

条件变量在Linux平台上的这种模型很难说好坏,在实际应用中,我们可以对

代码稍加改进就可以避免这种差异的发生。由于这种差异只会发生在触发没有被线程等待在条件变量的时刻,因此我们只需要掌握好触发的时机即可。最简单的做法是增加一个计数器记录等待线程的个数,在决定触发条件变量前检查该变量即可。

示例 使用 pthread_cond_wait() 和 pthread_cond_signal()

pthread_mutex_t count_lock;

pthread_cond_t count_nonzero;

unsigned count;

decrement_count()

{

pthread_mutex_lock(&count_lock);

while (count == 0)

pthread_cond_wait(&count_nonzero, &count_lock);

count = count – 1;

pthread_mutex_unlock(&count_lock);

}

increment_count()

{

pthread_mutex_lock(&count_lock);

if (count == 0)

pthread_cond_signal(&count_nonzero);

count = count + 1;

pthread_mutex_unlock(&count_lock);

}

(3) 注意Pthread_cond_wait条件返回时互斥锁的解锁问题

extern int pthread_cond_wait __P ((pthread_cond_t *__cond,pthread_mutex_t *__mutex));

   调用这个函数时,线程解开mutex指向的锁并被条件变量cond阻塞。线程可以被函数pthread_cond_signal和函数 pthread_cond_broadcast唤醒线程被唤醒后,它将重新检查判断条件是否满足,如果还不满足,一般说来线程应该仍阻塞在这里,被等待被下一次唤醒。如果在多线程中采用pthread_cond_wait来等待时,会首先释放互斥锁,当等待的信号到来时,再次获得互斥锁,因此在之后要注意手动解锁。举例如下:

#include

#include

#include

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /*初始化互斥锁*/

pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //初始化条件变量

void *thread1(void *);

void *thread2(void *);

int i=1;

int main(void)

{

pthread_t t_a;

pthread_t t_b;

pthread_create(&t_a,NULL,thread1,(void *)NULL);/*创建进程t_a*/

pthread_create(&t_b,NULL,thread2,(void *)NULL); /*创建进程t_b*/

pthread_join(t_b, NULL);/*等待进程t_b结束*/

pthread_mutex_destroy(&mutex);

pthread_cond_destroy(&cond);

exit(0);

}

void *thread1(void *junk)

{

for(i=1;i

{

printf(“IN one\n”);

pthread_mutex_lock(&mutex);//

if(i%3==0)

pthread_cond_signal(&cond);/*,发送信号,通知t_b进程*/

else

printf(“thead1:%d\n”,i);

pthread_mutex_unlock(&mutex);//*解锁互斥量*/

printf(“Up Mutex\n”);

sleep(3);

}

}

void *thread2(void *junk)

{

while(i

{

printf(“IN two \n”);

pthread_mutex_lock(&mutex);

if(i%3!=0)

pthread_cond_wait(&cond,&mutex);/*等待*/

printf(“thread2:%d\n”,i);

pthread_mutex_unlock(&mutex);

printf(“Down Mutex\n”);

sleep(3);

}

}

输出如下:

IN one

thead1:1

Up Mutex

IN two

IN one

thead1:2

Up Mutex

IN one

thread2:3

Down Mutex

Up Mutex

IN one

thead1:4

Up Mutex

IN two

IN one

thead1:5

Up Mutex

IN one

Up Mutex

thread2:6

Down Mutex

IN two

thread2:6

Down Mutex

IN one

thead1:7

Up Mutex

IN one

thead1:8

Up Mutex

IN two

IN one

Up Mutex

thread2:9

Down Mutex

注意蓝色的地方,有2个thread2:6,其实当这个程序多执行几次,i=3和i=6时有可能多打印几个,这里就是竞争锁造成的了。

(4)另外要注意的Pthread_cond_timedwait等待的是绝对时间,这个和WaitForSingleObject是不同的,Pthread_cond_timedwait在网上也有讨论。如下:这个问题比较经典,我把它搬过来。

thread_a :

pthread_mutex_lock(&mutex);

//do something

pthread_mutex_unlock(&mutex)

thread_b:

pthread_mutex_lock(&mutex);

//do something

pthread_cond_timedwait(&cond, &mutex, &tm);

pthread_mutex_unlock(&mutex)

有如上两个线程thread_a, thread_b,现在如果a已经进入了临界区,而b同时超时了,那么b会从pthread_cond_timedwait返回吗?如果能返回,那岂不是a,b都在临界区?如果不能返回,那pthread_cond_timedwait的定时岂不是就不准了?

大家讨论有价值的2点如下:

(1) pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *external_mutex, const struct timespec *abstime) — This function is a time-based variant of pthread_cond_wait. It waits up to abstime amount of time for cv to be notified. If abstime elapses before cv is notified, the function returns back to the caller with an ETIME result, signifying that a timeout has occurred. Even in the case of timeouts, the external_mutex will be locked when pthread_cond_timedwait returns.

(2) 2.1 pthread_cond_timedwait行为和pthread_cond_wait一样,在返回的时候都要再次lock mutex.

2 .2pthread_cond_timedwait所谓的如果没有等到条件变量,超时就返回,并不确切。

如果pthread_cond_timedwait超时到了,但是这个时候不能lock临界区,pthread_cond_timedwait并不会立即返回,但是在pthread_cond_timedwait返回的时候,它仍在临界区中,且此时返回值为ETIMEDOUT。

关于pthread_cond_timedwait超时返回的问题,我也认同观点2。

附录:

 int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict_attr,void*(*start_rtn)(void*),void *restrict arg);

  返回值:若成功则返回0,否则返回出错编号

  返回成功时,由tidp指向的内存单元被设置为新创建线程的线程ID。attr参数用于制定各种不同的线程属性。新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无指针参数arg,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg的参数传入。

linux下用C开发多线程程序,Linux系统下的多线程遵循POSIX线程接口,称为pthread。

由 restrict 修饰的指针是最初唯一对指针所指向的对象进行存取的方法,仅当第二个指针基于之一个时,才能对对象进行存取。对对象的存取都限定于基于由 restrict 修饰的指针表达式中。 由 restrict 修饰的指针主要用于函数形参,或指向由 malloc() 分配的内存空间。restrict 数据类型不改变程序的语义。 编译器能通过作出 restrict 修饰的指针是存取对象的唯一方法的假设,更好地优化某些类型的例程。

  之一个参数为指向线程标识符的指针。

  第二个参数用来设置线程属性。

  第三个参数是线程运行函数的起始地址。

  第四个参数是运行函数的参数。

因为pthread不是linux系统的库,所以在编译时注意加上-lpthread参数,以调用静态链接库。

终止线程:

如果在进程中任何一个线程中调用exit或_exit,那么整个进行会终止,线程正常的退出方式有:

(1) 线程从启动例程中返回(return)

(2) 线程可以被另一个进程终止(kill);

(3) 线程自己调用pthread_exit函数

#include

pthread_exit

线程等待:

int pthread_join(pthread_t tid,void **rval_ptr)

函数pthread_join用来等待一个线程的结束。函数原型为:

  extern int pthread_join __P (pthread_t __th, void **__thread_return);

之一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。

对于windows线程的创建东西,就不列举了,msdn上 一搜就出来了。呵呵。今天就讲到这里吧,希望是抛砖引玉,大家一起探讨,呵呵。部分内容我也是参考internet的,特此对原作者表示感谢!

在linux中运用多线程知识的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于在linux中运用多线程知识,Linux多线程编程指南:提高程序性能的有效手段,linux 多线程环境下的几种锁机制,浅谈linux 多线程编程和 windows 多线程编程的异同的信息别忘了在本站进行查找喔。

创新互联(cdcxhl.com)提供稳定的云服务器,香港云服务器,BGP云服务器,双线云服务器,高防云服务器,成都云服务器,服务器托管。精选钜惠,欢迎咨询:028-86922220。

新闻标题:Linux多线程编程指南:提高程序性能的有效手段(在linux中运用多线程知识)
本文网址:http://www.shufengxianlan.com/qtweb/news34/495984.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联