2024年9月linux多线程编程(Linux下如何实现shell多线程编程以提高应用程序的响应)

 更新时间:2024-09-21 08:54:34

  ⑴linux多线程编程(Linux下如何实现shell多线程编程以提高应用程序的响应

  ⑵其实并不是所有的程序都必须采用多线程,浅谈linux多线程编程和windows多线程编程的异同很早以前就想写写linux下多线程编程和windows下的多线程编程了,这个函数是一个线程阻塞的函数,如果在多线程中采用pthread_cond_wait来等待时,执不执行push后的函数就看pop函数中的参数是不是为了,不执行push函数中的清除函数,有时在个线程所需的时间不相同的时候,即:当pop函数参数不为时。

  ⑶Linux下如何实现shell多线程编程以提高应用程序的响应

  ⑷Linux中多线程编程拥有提高应用程序的响应、使多cpu系统更加有效等优点,下面小编将通过Linux下shell多线程编程的例子给大家讲解下多线程编程的过程,一起来了解下吧。

  ⑸#!/bin/bash

  ⑹#———————————————————————————–

  ⑺#此例子说明了一种用wait、read命令模拟多线程的一种技巧

  ⑻#此技巧往往用于多主机检查,比如ssh登录、ping等等这种单进程比较慢而不耗费cpu的情况

  ⑼#还说明了多线程的控制

  ⑽#———————————————————————————–

  ⑾functiona_sub

  ⑿#此处定义一个函数,作为一个线程(子进程

  ⒀sleep#线程的作用是sleeps

  ⒁tmp_fifofile=“/tmp/$.fifo”mkfifo$tmp_fifofile#新建一个fifo类型的文件

  ⒂exec《》$tmp_fifofile#将fd指向fifo类型

  ⒃rm$tmp_fifofilethread=#此处定义线程数

  ⒄((i=;i《$thread;i++;doecho

  ⒅done》&#事实上就是在fd中放置了$thread个回车符

  ⒆((i=;i《;i++;do#次循环,可以理解为个主机,或其他

  ⒇read-u#一个read-u命令执行一次,就从fd中减去一个回车符,然后向下执行,

  ⒈#fd中没有回车符的时候,就停在这了,从而实现了线程数量控制

  ⒉{#此处子进程开始执行,被放到后台

  ⒊{#此处可以用来判断子进程的逻辑

  ⒋echo“a_subisfinished”

  ⒌{echo“suberror”

  ⒍echo》&#当进程结束以后,再向fd中加上一个回车符,即补上了read-u减去的那个

  ⒎&donewait#等待所有的后台子进程结束

  ⒏exec》&-#关闭dfexit

  ⒐mkfifotmpfile

  ⒑和linux中的命令

  ⒒mknodtmpfilep

  ⒓效?果相同。区别是mkfifo为POSIX标准,因此推荐使用它。该命令创建了一个先入先出的管道文件,并为其分配文件标志符。管道文件是进程之间通信的一种方式,注意这一句很重要

  ⒔exec《》$tmp_fifofile#将fd指向fifo类型

  ⒕如果没有这句,在向文件$tmp_fifofile或者&写入数据时,程序会被阻塞,直到有read读出了管道文件中的数据为止。而执行了上面这一句后就可以在程序运行期间不断向fifo类型的文件写入数据而不会阻塞,并且数据会被保存下来以供read程序读出。

  ⒖time。/multithread.sh》/dev/null

  ⒗最终运算时间:/=组(每组+组(个《组成一个组=组,每组花费时间:秒,

  ⒘传统非多线程的代码运算时间:*=秒。

  ⒙上面就是Linux下shell多线程编程的实例介绍了,使用多线程编程还能够改善程序结构,有兴趣的朋友不妨试试看吧。

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

  ⒛很早以前就想写写linux下多线程编程和windows下的多线程编程了,但是每当写时又不知道从哪个地方写起,怎样把自己知道的东西都写出来,下面我就谈谈linux多线程及线程同步,并将它和windows的多线程进行比较,看看他们之间有什么相同点和不同的地方。其实最开始我是搞windows下编程的,包括windows编程,windows驱动,包括usb驱动,ndis驱动,pci驱动,驱动等等,同时也一条龙服务,做windows下的应用程序开发,后面慢慢的我又对linux开发产生比较深的兴趣和爱好,就转到搞linux开发了。在接下来的我还会写一些博客,主要是写linux编程和windows编程的区别吧,现在想写的是linux下usb驱动和windows下usb驱动开发的区别,这些都是后话,等我将linux多线程和windows多线程讲解完后,我再写一篇usb驱动,谈谈windows和linuxusb驱动的东东。好了,言归正传。开始将多线程了。首先我们讲讲为什么要采用多线程编程,其实并不是所有的程序都必须采用多线程,有些时候采用多线程,性能还没有单线程好。所以我们要搞清楚,什么时候采用多线程。采用多线程的好处如下:()因为多线程彼此之间采用相同的地址空间,共享大部分的数据,这样和多进程相比,代价比较节俭,因为多进程的话,启动新的进程必须分配给它独立的地址空间,这样需要数据表来维护代码段,数据段和堆栈段等等。()多线程和多进程相比,一个明显的优点就是线程之间的通信了,对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。但是对于多线程就不一样了。他们之间可以直接共享数据,比如最简单的方式就是共享全局变量。但是共享全部变量也要注意哦,呵呵,必须注意同步,不然后果你知道的。呵呵。()在多cpu的情况下,不同的线程可以运行不同的cpu下,这样就完全并行了。反正我觉得在这种情况下,采用多线程比较理想。比如说你要做一个任务分个步骤,你为提高工作效率,你可以多线程技术,开辟个线程,第一个线程就做第一步的工作,第个线程就做第步的工作。但是你这个时候要注意同步了。因为只有第一步做完才能做第步的工作。这时,我们可以采用同步技术进行线程之间的通信。针对这种情况,我们首先讲讲多线程之间的通信,在windows平台下,多线程之间通信采用的方法主要有:()共享全局变量,这种方法是最容易想到的,呵呵,那就首先讲讲吧,比如说吧,上面的问题,第一步要向第步传递收据,我们可以之间共享全局变量,让两个线程之间传递数据,这时主要考虑的就是同步了,因为你后面的线程在对数据进行操作的时候,你第一个线程又改变了数据的内容,你不同步保护,后果很严重的。你也知道,这种情况就是读脏数据了。在这种情况下,我们最容易想到的同步方法就是设置一个boolflag了,比如说在第个线程还没有用完数据前,第一个线程不能写入。有时在个线程所需的时间不相同的时候,怎样达到最大效率的同步,就比较麻烦了。咱们可以多开几个缓冲区进行操作。就像生产者消费者一样了。如果是个线程一直在跑的,由于时间不一致,缓冲区迟早会溢出的。在这种情况下就要考虑了,是不让数据写入还是让数据覆盖掉老的数据,这时候就要具体问题具体分析了。就此打住,呵呵。就是用bool变量控制同步,linux和windows是一样的。既然讲道了这里,就再讲讲其它同步的方法。同样针对上面的这个问题,共享全局变量同步问题。除了采用bool变量外,最容易想到的方法就是互斥量了。呵呵,也就是传说中的加锁了。windows下加锁和linux下加锁是类似的。采用互斥量进行同步,要想进入那段代码,就先必须获得互斥量。linux上互斥量的函数是:windows下互斥量的函数有:createmutex创建一个互斥量,然后就是获得互斥量waitforsingleobject函数,用完了就释放互斥量ReleaseMutex(hMutex),当减到的时候内核会才会释放其对象。下面是windows下与互斥的几个函数原型。HANDLEWINAPICreateMutex(__inLPSECURITY_ATTRIBUTESlpMutexAttributes,__inBOOLbInitialOwner,__inLPCTSTRlpName);可以可用来创建一个有名或无名的互斥量对象第一参数可以指向一个结构体SECURITY_ATTRIBUTES一般可以设为null;第二参数指当时的函数是不是感应感应状态FALSE为当前拥有者不会创建互斥第三参数指明是否是有名的互斥对象如果是无名用null就好。DWORDWINAPIWaitForSingleObject(__inHANDLEhHandle,__inDWORDdwMilliseconds);第一个是创建的互斥对象的句柄。第二个是表示将在多少时间之后返回如果设为宏INFINITE则不会返回直到用户自己定义返回。对于linux操作系统,互斥也是类似的,只是函数不同罢了。在linux下,和互斥相关的几个函数也要闪亮登场了。pthread_mutex_init函数:初始化一个互斥锁;pthread_mutex_destroy函数:注销一个互斥锁;pthread_mutex_lock函数:加锁,如果不成功,阻塞等待;pthread_mutex_unlock函数:解锁;pthread_mutex_trylock函数:测试加锁,如果不成功就立即返回,错误码为EBUSY;至于这些函数的用法,google上一搜,就出来了,呵呵,在这里不多讲了。windows下还有一个可以用来保护数据的方法,也是线程同步的方式就是临界区了。临界区和互斥类似。它们之间的区别是,临界区速度快,但是它只能用来同步同一个进程内的多个线程。临界区的获取和释放函数如下:EnterCriticalSection()进入临界区;LeaveCriticalSection()离开临界区。对于多线程共享内存的东东就讲到这里了。()采用消息机制进行多线程通信和同步,windows下面的的消息机制的函数用的多的就是postmessage了。Linux下的消息机制,我用的较少,就不在这里说了,如果谁熟悉的,也告诉我,呵呵。()windows下的另外一种线程通信方法就是事件和信号量了。同样针对我开始举得例子,个线程同步,他们之间传递信息,可以采用事件(Event)或信号量(Semaphore),比如第一个线程完成生产的数据后,就必须告诉第个线程,他已经把数据准备好了,你可以来取走了。第个线程就把数据取走。呵呵,这里可以采用消息机制,当第一个线程准备好数据后,就直接postmessage给第个线程,按理说采用postmessage一个线程就可以搞定这个问题了。呵呵,不是重点,省略不讲了。对于linux,也有类似的方法,就是条件变量了,呵呵,这里windows和linux就有不同了。要特别讲讲才行。对于windows,采用事件和信号量同步时候,都会使用waitforsingleobject进行等待的,这个函数的第一个参数是一个句柄,在这里可以是Event句柄,或Semaphore句柄,第个参数就是等待的延迟,最终等多久,单位是ms,如果这个参数为INFINITE,那么就是无限等待了。释放信号量的函数为ReleaseSemaphore(;释放事件的函数为SetEvent。当然使用这些东西都要初始化的。这里就不讲了。Msdn一搜,神马都出来了,呵呵。神马都是浮云!对于linux操作系统,是采用条件变量来实现类似的功能的。Linux的条件变量一般都是和互斥锁一起使用的,主要的函数有:pthread_mutex_lock,pthread_mutex_unlock,pthread_cond_initpthread_cond_signalpthread_cond_waitpthread_cond_timewait为了和windows操作系统进行对比,我用以下表格进行比较:对照以上表格,总结如下:()Pthread_cleanup_push,Pthread_cleanup_pop:这一对函数push和pop的作用是当出现异常退出时,做一些清除操作,即当在push和pop函数之间异常退出,包括调用pthread_exit退出,都会执行push里面的清除函数,如果有多个push,注意是是栈,先执行后面的那个函数,在执行前面的函数,但是注意当在这个函数之间通过return退出的话,执不执行push后的函数就看pop函数中的参数是不是为了。还有当没有异常退出时,等同于在这里面return退出的情况,即:当pop函数参数不为时,执行清除操作,当pop函数参数为时,不执行push函数中的清除函数。(linux的pthread_cond_signal和SetEvent的不同点Pthread_cond_singal释放信号后,当没有Pthread_cond_wait,信号马上复位了,这点和SetEvent不同,SetEvent是不会复位的。详解如下:条件变量的置位和复位有种常用模型:第一种模型是当条件变量置位时(signaled)以后,如果当前没有线程在等待,其状态会保持为置位(signaled),直到有等待的线程进入被触发,其状态才会变为unsignaled,这种模型以采用Windows平台上的Auto-setEvent为代表。第种模型则是Linux平台的pthread所采用的模型,当条件变量置位(signaled)以后,即使当前没有任何线程在等待,其状态也会恢复为复位(unsignaled)状态。条件变量在Linux平台上的这种模型很难说好坏,在实际应用中,我们可以对代码稍加改进就可以避免这种差异的发生。由于这种差异只会发生在触发没有被线程等待在条件变量的时刻,因此我们只需要掌握好触发的时机即可。最简单的做法是增加一个计数器记录等待线程的个数,在决定触发条件变量前检查该变量即可。示例使用pthread_cond_wait()和pthread_cond_signal()pthread_mutex_tcount_lock;pthread_cond_tcount_nonzero;unsignedcount;decrement_count(){pthread_mutex_lock(&count_lock);while(count==)pthread_cond_wait(&count_nonzero,&count_lock);count=count-;pthread_mutex_unlock(&count_lock);}increment_count(){pthread_mutex_lock(&count_lock);if(count==)pthread_cond_signal(&count_nonzero);count=count+;pthread_mutex_unlock(&count_lock);}()注意Pthread_cond_wait条件返回时互斥锁的解锁问题externintpthread_cond_wait__P((pthread_cond_t*__cond,pthread_mutex_t*__mutex));调用这个函数时,线程解开mutex指向的锁并被条件变量cond阻塞。线程可以被函数pthread_cond_signal和函数pthread_cond_broadcast唤醒线程被唤醒后,它将重新检查判断条件是否满足,如果还不满足,一般说来线程应该仍阻塞在这里,被等待被下一次唤醒。如果在多线程中采用pthread_cond_wait来等待时,会首先释放互斥锁,当等待的信号到来时,再次获得互斥锁,因此在之后要注意手动解锁。举例如下:#include#include#includepthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;/*初始化互斥锁*/pthread_cond_tcond=PTHREAD_COND_INITIALIZER;//初始化条件变量void*thread(void*);void*thread(void*);inti=;intmain(void){pthread_tt_a;pthread_tt_b;pthread_create(&t_a,NULL,thread,(void*)NULL);/*创建进程t_a*/pthread_create(&t_b,NULL,thread,(void*)NULL);/*创建进程t_b*/pthread_join(t_b,NULL);/*等待进程t_b结束*/pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);exit();}void*thread(void*junk){for(i=;i《=;i++){printf(“INone

  “);pthread_mutex_lock(&mutex);//if(i%==)pthread_cond_signal(&cond);/*,发送信号,通知t_b进程*/elseprintf(“thead:%d

  “,i);pthread_mutex_unlock(&mutex);//*解锁互斥量*/printf(“UpMutex

  “);sleep();}}void*thread(void*junk){while(i《){printf(“INtwo

  “);pthread_mutex_lock(&mutex);if(i%!=)pthread_cond_wait(&cond,&mutex);/*等待*/printf(“thread:%d

  “,i);pthread_mutex_unlock(&mutex);printf(“DownMutex

  “);sleep();}}输出如下:INohead:UpMutexINtwoINohead:UpMutexINohread:DownMutexUpMutexINohead:UpMutexINtwoINohead:UpMutexINoneUpMutexthread:DownMutexINtwothread:DownMutexINohead:UpMutexINohead:UpMutexINtwoINoneUpMutexthread:DownMutex注意蓝色的地方,有个thread:,其实当这个程序多执行几次,i=和i=时有可能多打印几个,这里就是竞争锁造成的了。()另外要注意的Pthread_cond_timedwait等待的是绝对时间,这个和WaitForSingleObject是不同的,Pthread_cond_timedwait在网上也有讨论。如下:这个问题比较经典,我把它搬过来。thread_a:pthread_mutex_lock(&mutex);//dosomethingpthread_mutex_unlock(&mutex)thread_b:pthread_mutex_lock(&mutex);//dosomethingpthread_cond_timedwait(&cond,&mutex,&tm);pthread_mutex_unlock(&mutex)有如上两个线程thread_a,thread_b,现在如果a已经进入了临界区,而b同时超时了,那么b会从pthread_cond_timedwait返回吗?如果能返回,那岂不是a,b都在临界区?如果不能返回,那pthread_cond_timedwait的定时岂不是就不准了?大家讨论有价值的点如下:(pthread_cond_timedwait(pthread_cond_t*cv,pthread_mutex_t*external_mutex,conststructtimespec*abstime)--Thisfunctionisatime-basedvariantofpthread_cond_wait.Itwaitsuptoabstimeamountoftimeforcvtobenotified.Ifabstimeelapsesbeforecvisnotified,thefunctionreturnsbacktothecallerwithaIMEresult,signifyingthatatimeouthasourred.Eveninthecaseoftimeouts,theexternal_mutexwillbelockedwhenpthread_cond_timedwaitreturns.(.pthread_cond_timedwait行为和pthread_cond_wait一样,在返回的时候都要再次lockmutex..pthread_cond_timedwait所谓的如果没有等到条件变量,超时就返回,并不确切。如果pthread_cond_timedwait超时到了,但是这个时候不能lock临界区,pthread_cond_timedwait并不会立即返回,但是在pthread_cond_timedwait返回的时候,它仍在临界区中,且此时返回值为ETIMEDOUT。关于pthread_cond_timedwait超时返回的问题,我也认同观点。附录:intpthread_create(pthread_t*restricttidp,constpthread_attr_t*restrict_attr,void*(*start_rtn)(void*),void*restrictarg);返回值:若成功则返回,否则返回出错编号返回成功时,由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,那么整个进行会终止,线程正常的退出方式有:(线程从启动例程中返回(return)(线程可以被另一个进程终止(kill;(线程自己调用pthread_exit函数#includepthread_exit线程等待:intpthread_join(pthread_ttid,void**rval_ptr)函数pthread_join用来等待一个线程的结束。函数原型为:externintpthread_join__P(pthread_t__th,void**__thread_return);第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。对于windows线程的创建东西,就不列举了,msdn上一搜就出来了。呵呵。今天就讲到这里吧,希望是抛砖引玉,大家一起探讨,呵呵。部分内容我也是参考inter的,特此对原作者表示感谢!

您可能感兴趣的文章:

相关文章