当前位置:首页 » 编程软件 » linuxc多线程编程

linuxc多线程编程

发布时间: 2022-08-10 04:46:13

linux系统下,c语言pthread多线程编程传参问题

3个线程使用的都是同一个info

代码 Info_t *info= (Info_t *)malloc(sizeof(Info_t));只创建了一个info

pthread_create(&threads[i],NULL,calMatrix,(void *)info); 三个线程使用的是同一个

我把你的代码改了下:

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>

intmtc[3]={0};//resultmatrix

typedefstruct
{
intprank;
int*mta;
int*mtb;
}Info_t;

void*calMatrix(void*arg)
{
inti;
Info_t*info=(Info_t*)arg;
intprank=info->prank;
fprintf(stdout,"calMatrix:prankis%d ",prank);

for(i=0;i<3;i++)
mtc[prank]+=info->mta[i]*info->mtb[i];

returnNULL;
}

intmain(intargc,char**argv)
{
inti,j,k=0;
intmta[3][3];
intmtb[3]={1};
Info_t*info=(Info_t*)malloc(sizeof(Info_t)*3);

for(i=0;i<3;i++)
for(j=0;j<3;j++)
mta[i][j]=k++;
/*3threads*/
pthread_t*threads=(pthread_t*)malloc(sizeof(pthread_t)*3);
fprintf(stdout," ");fflush(stdout);
for(i=0;i<3;i++)
{
info[i].prank=i;
info[i].mta=mta[i];
info[i].mtb=mtb;
pthread_create(&threads[i],NULL,calMatrix,(void*)(&info[i]));
}
for(i=0;i<3;i++)
pthread_join(threads[i],NULL);

fprintf(stdout," ====thematrixresult==== ");
fflush(stdout);

for(i=0;i<3;i++)
{
fprintf(stdout,"mtc[%d]=%d ",i,mtc[i]);
fflush(stdout);
}
return0;
}

矩阵的计算我忘记了,你运行看看结果对不对

② linux下多进程或者多线程编程的问题。新手,望指教!

你好,多进程或多线程,都不会阻塞当前语句代码。为了您的理解,我就大胆举下面两个例子:
多进程:你可以看成是本来是一条路的,现在从中间拆成两条,然后每一条路都有属于自己这条路的代码在运行。
多线程:你可以看成是一条路,然后分出车道,比如左车道和右车道甚至是停车道,然后每条车道都单独通车,其他车道的不能对这条车道进行干扰。

所以,把一条路从中间拆成两条,成本是很高的。但是把一条路分车道,成本就不是很高了。
对于您提出的main函数的疑问,当main函数最后执行完毕,程序退出后,所有的进程包括线程,都会被关闭的,哪怕你的程序中没有关闭,操作系统也会帮你关闭的,现在的操作系统都非常的完善了。当然,也存在有线程或进程不被释放的特殊情况,最好在编程中要记得释放。

③ 如何看懂《Linux多线程服务端编程

:进程线程 每进程自独立址空间同进程同进程系统功能划重要决策点《Erlang程序设计》[ERL]进程比喻: 每自记忆(内存)与通谈(消息传递)交流谈既面谈(同台服务器)电谈(同服务器中国络通信)面谈电谈区别于面谈立即知道否死(crash,SIGCHLD)电谈能通周期性跳判断否着 些比喻设计布式系统采取角色扮演团队几各自扮演进程角色由进程代码决定(管登录、管消息发、管买卖等等)每自记忆知道别记忆要想知道别看能通交谈(暂考虑共享内存种IPC)思考: ·容错:万突死 ·扩容:新途加进 ·负载均衡:甲挪给乙做 ·退休:甲要修复bug先别派新任务等做完手事情重启 等等各种场景十便利 线程特点共享址空间高效共享数据台机器进程能高效共享代码段(操作系统映射同物理内存)能共享数据进程量共享内存等于进程程序线程写掩耳盗铃 线程价值我认更发挥核处理器(multi-cores)效能单核代线程没价值(想:要完任务CPU密集型线程没优势甚至线程切换销线程反更慢;要完任务既CPU计算磁盘或中国络IO则使用线程处某线程IO阻塞OS调度其线程执行虽效率确实要比任务顺序执行效率要高种类型任务通单线程non-blocking IO+IO multiplexing模型(事件驱)提高效率采用线程式带能仅仅编程简单已)Alan Cox说:A 中国puter is a state machine.Threads are for people who can’t program state machines.(计算机台状态机线程给些能编写状态机程序准备)块CPU、执行单元确实Alan Cox所说按状态机思路写程序高效 二:单线程服务器用编程模型 据我解高性能中国络程序使用广泛恐怕要数non-blocking IO + IO multiplexing种模型即Reactor模式 non-blocking IO + IO multiplexing种模型程序基本结构事件循环(event loop)事件驱(event-driven)事件调式实现业务逻辑: [cpp] view plain //代码仅示意没完整考虑各种情况 while(!done) { int timeout_ms = max(1000, getNextTimedCallback()); int retval = poll(fds, nfds, timeout_ms); if (retval0){ 处理IO事件调用户IO event handler } } } select(2)/poll(2)伸缩性面足(描述符效率较低)Linux替换epoll(4)其操作系统应高性能替代品 Reactor模型优点明显编程难效率错仅用于读写socket连接建立(connect(2)/accept(2))甚至DNS解析都用非阻塞式进行提高并发度吞吐量(throughput)于IO密集应用错选择lighttpd内部fdevent结构十精妙值习 基于事件驱编程模型其本质缺点要求事件调函数必须非阻塞于涉及中国络IO请求响应式协议容易割裂业务逻辑使其散布于调函数相容易理解维护 三:线程服务器用编程模型 概几种: a:每请求创建线程使用阻塞式IO操作Java 1.4引NIO前Java中国络编程推荐做惜伸缩性佳(请求太操作系统创建许线程) b:使用线程池同使用阻塞式IO操作与第1种相比提高性能措施 c:使用non-blocking IO + IO multiplexing即Java NIO式 d:Leader/Follower等高级模式 默认情况我使用第3种即non-blocking IO + one loop per thread模式编写线程C++中国络服务程序 1:one loop per thread 种模型程序每IO线程event loop用于处理读写定事件(论周期性单)代码框架跟单线程服务器用编程模型节 libev作者说: One loop per thread is usually a good model. Doing this is almost never wrong, some times a better-performance model exists, but it is always a good start. 种式处: a:线程数目基本固定程序启候设置频繁创建与销毁 b:便线程间调配负载 c:IO事件发线程固定同TCP连接必考虑事件并发 Event loop代表线程主循环需要让哪线程干timer或IO channel(TCP连接)注册哪线程loop即:实性要求connection单独用线程;数据量connection独占线程并数据处理任务摊另几计算线程(用线程池);其要辅助性connections共享线程 比dbproxy线程用于专门处理客户端发管理命令;线程用于处理客户端发MySQL命令与端数据库通信执行该命令该任务配给所事件线程处理 于non-trivial(定规模)服务端程序般采用non-blocking IO + IO multiplexing每connection/acceptor都注册某event loop程序event loop每线程至event loop 线程程序event loop提更高要求线程安全要允许线程往别线程loop塞东西loop必须线程安全 dbproxy线程向其线程发任务通管道队列实现比主线程accept连接表示该连接结构放入队列并向管道写入字节计算线程自event loop注册管道读事件旦数据读尝试队列取任务 2:线程池 于没IO光计算任务线程使用event loop点浪费使用种补充案即用blocking queue实现任务队列: [cpp] view plain typedef boost::functionFunctor; BlockingQueue taskQueue; //线程安全全局阻塞队列 //计算线程 void workerThread() { while (running) //running变量全局标志 { Functor task = taskQueue.take(); //this blocks task(); //产品代码需要考虑异处理 } } // 创建容量(并发数)N线程池 int N = num_of_中国puting_threads; for (int i = 0; i < N; ++i) { create_thread(&workerThread); //启线程 } //向任务队列追加任务 Foo foo; //Foocalc()员函数 boost::function task = boost::bind(&Foo::calc&foo); taskQueue.post(task); 除任务队列用BlockingQueue实现数据产者消费者队列即T数据类型非函数象queue消费者拿数据进行处理其实本质 3:总结 总结言我推荐C++线程服务端编程模式:one (event) loop per thread + thread pool: event loop用作IO multiplexing配合non-blockingIO定器; thread pool用做计算具体任务队列或产者消费者队列 种式写服务器程序需要优质基于Reactor模式中国络库支撑muo中国络库比dbproxy使用libevent 程序具体用几loop、线程池等参数需要根据应用设定基本原则阻抗匹配(解释见)使CPUIO都能高效运作所谓阻抗匹配原则: 池线程执行任务密集计算所占间比重 P (0 < P <= 1)系统共 C CPU让 C CPU 跑满载线程池经验公式 T = C/P(T hint考虑 P 值估计准确T 佳值浮 50%) 我再讲经验公式先验证边界条件确性 假设 C = 8P = 1.0线程池任务完全密集计算T = 8要 8 线程能让 8 CPU 饱再没用 CPU 资源已经耗光 假设 C = 8P = 0.5线程池任务半计算半等 IO T = 16考虑操作系统能灵合理调度 sleeping/writing/running 线程概 16 50%繁忙线程能让 8 CPU 忙停启更线程并能提高吞吐量反增加文切换销降低性能 P < 0.2公式适用T 取固定值比 5*C 另外公式 C 定 CPU 总数配给项任务 CPU 数目比 8 核机器 4 核做项任务 C=4 四:进程间通信用TCP Linux进程间通信式:匿名管道(pipe)、具名管道(FIFO)、POSIX消息队列、共享内存、信号(signals)及Socket同步原语互斥器(mutex)、条件变量(condition variable)、读写锁(reader-writer lock)、文件锁(record locking)、信号量(semaphore)等等 进程间通信我首选Sockets(主要指TCP我没用UDP考虑Unix domain协议)其处于: 跨主机具伸缩性反都进程台机器处理能力够自能用台机器处理进程散同局域中国台机器程序改改host:port配置能继续用; TCP socketspipe都操作文件描述符用收发字节流都read/write/fcntl/select/poll等同TCP双向Linuxpipe单向进程间双向通信两文件描述符便;且进程要父关系才能用pipe些都限制pipe使用; TCP port由进程独占且进程退操作系统自收文件描述符即使程序意外退给系统留垃圾程序重启能比较容易恢复需要重启操作系统(用跨进程mutex风险);且port独占防止程序重复启面进程抢port自没初始化避免造意料外结; 与其IPC相比TCP协议处记录、重现tcpmpWireshark解决两进程间协议状态争端帮手性能(吞吐量、延迟)析利器我借编写布式程序自化归测试用tcp类工具进行压力测试TCP能跨语言服务端客户端必使用同种语言 布式系统软件设计功能划般应该进程单位宏观看布式系统由运行台机器进程组进程间采用TCP连接通信 使用TCP连接处两点:容易定位布式系统服务间依赖关系要机器运行netstat -tpna|grep 能立刻列用某服务客户端址(Foreign Address列)客户端机器用netstat或lsof命令找哪进程发起连接TCP短连接UDP则具备特性二通接收发送队列度较容易定位中国络或程序故障运行候netstat打印Recv-QSend-Q都应该接近0或者0附近摆Recv-Q保持变或持续增加则通意味着服务进程处理速度变慢能发死锁或阻塞Send-Q保持变或持续增加能服务器太忙、及处理能中国络间某路由器或交换机故障造丢包甚至服务器掉线些素都能表现数据发送通持续监控Recv-QSend-Q能及早预警性能或用性故障服务端线程阻塞造Recv-Q客户端Send-Q激增例: [cpp] view plain $netstat -tn Proto Recv-Q Send-Q Local Address Foreign tcp 78393 0 10.0.0.10:2000 10.0.0.10:39748 #服务端连接 tcp 0 132608 10.0.0.10:39748 10.0.0.10:2000 #客户端连接 tcp 0 52 10.0.0.10:22 10.0.0.4:55572 五:线程服务器适用场合 要台核机器提供种服务或执行任务用模式: a:运行单线程进程; b:运行线程进程; c:运行单线程进程; d:运行线程进程; 考虑场景:使用速率50MB/s数据压缩库进程创建销毁销800微秒线程创建销毁销50微秒何执行压缩任务 要偶尔压缩1GB文本文件预计运行间20s起进程做合理进程启销毁销远远于实际任务耗 要经压缩500kB文本数据预计运行间10ms每都起进程 似乎点浪费每单独起线程做 要频繁压缩10kB文本数据预计运行间200微秒每起线程似 乎浪费直接前线程搞定用线程池每压缩任务交给线程池避免阻塞前线程(特别要避免阻塞IO线程) 由见线程并万灵丹(silver bullet) 1:必须使用单线程场合 据我所知两种场合必须使用单线程: a:程序能fork(2); 实际编程应该保证单线程程序能进行fork(2)线程程序能调用fork(2)做遇麻烦: fork般能线程程序调用Linuxfork克隆前线程thread of control隆其线程fork除前线程外其线程都消失 造种危险局面其线程能处于临界区内持某锁突死亡再没机解锁进程试图再同mutex加锁立即死锁fork进程相于处于signal handler(知道调用fork父进程线程调用函数信号发场景)能调用线程安全函数(除非重入)能调用异步信号安全函数比fork进程能调用: mallocmalloc访问全局状态几乎肯定加锁; 任何能配或释放内存函数比snprintf; 任何Pthreads函数; printf系列函数其线程能恰持stdout/stderr锁; 除man 7 signal明确列信号安全函数外任何函数 线程调用fork唯安全做fork立即调用exec执行另程序彻底隔断进程与父进程联系 线程环境调用fork产进程进程内部存线程父进程调用fork线程副本 使用fork创建进程进程通继承整址空间副本父进程继承所互斥量、读写锁条件变量状态父进程某线程占锁则进程同占些锁问题进程并包含占锁线程副本所进程没办知道占哪些锁并且需要释放哪些锁 尽管Pthread提供pthread_atfork函数试图绕问题使代码变混乱《Programming With Posix Threads》书作者说:Avoid using fork in threaded code except where the child process will immediately exec a new program. b:限制程序CPU占用率; 容易理解比8核服务器单线程程序即便发busy-wait占满1core其CPU使用率12.5%种坏情况系统87.5%计算资源供其服务进程使用 于些辅助性程序必须主要服务进程运行同台机器做单线程能避免抢夺系统计算资

④ linux下C语言编程线程有什么好处呢

进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于:

线程的划分尺度小于进程,使得多线程程序的并发性搞。

另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

进程(Process)是最初定义在Unix等多用户、多任务操作系统环境下用于表示应用程序在内存环境中基本执行单元的概念。以Unix操作系统为例,进程是Unix操作系统环境中的基本成分、是系统资源分配的基本单位。Unix操作系统中完成的几乎所有用户管理和资源分配等工作都是通过操作系统对应用程序进程的控制来实现的。

一般你运行一个应用程序,就生成了一个进程, 这个进程拥有自己的内存空间,

这个进程还可以内部生成多个线程, 这些线程之间共用一个进程的内存空存空间,所以线程之间共享内存是很容易做到的,多线程协作比多进程协作快一些,而且安全.

在windows跟unix上面,进程,线程的实现方法都是不一样的.

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

首先我们讲讲为什么要采用多线程编程,其实并不是所有的程序都必须采用多线程,有些时候采用多线程,性能还没有单线程好。所以我们要搞清楚,什么时候采用多线程。采用多线程的好处如下:
(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<=9;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<9)
{
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下用C++创建新线程

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
void* thread(void* arg)
{
printf ("The child process...\n");
}

int main(int argc, char *argv[])
{
pthread_t id;
int i,ret;
ret=pthread_create(&id,NULL,(void *)thread,NULL);
if(ret!=0)
{
printf ("Create pthread error!\n");
exit (1);
}

}
程序如上就可以编译。
它属于linux下C编程中多线程编程的范围。
用命令
gcc -lpthread 1.c -o 1
./1
就可以出结果。
多线程编程的基础可以参考
http://hi..com/huifeng00/blog/item/ed13ddc0d6c59c170ff47715.html

⑦ Linux C 怎么实现两个线程同步读取两个内存的数据

在Linux系统中使用C/C++进行多线程编程时,我们遇到最多的就是对同一变量的多线程读写问题,大多情况下遇到这类问题都是通过锁机制来处理,但这对程序的性能带来了很大的影响,当然对于那些系统原生支持原子操作的数据类型来说,我们可以使用原子操作来处理,这能对程序的性能会得到一定的提高。那么对于那些系统不支持原子操作的自定义数据类型,在不使用锁的情况下如何做到线程安全呢?本文将从线程局部存储方面,简单讲解处理这一类线程安全问题的方法。

一、数据类型
在C/C++程序中常存在全局变量、函数内定义的静态变量以及局部变量,对于局部变量来说,其不存在线程安全问题,因此不在本文讨论的范围之内。全局变量和函数内定义的静态变量,是同一进程中各个线程都可以访问的共享变量,因此它们存在多线程读写问题。在一个线程中修改了变量中的内容,其他线程都能感知并且能读取已更改过的内容,这对数据交换来说是非常快捷的,但是由于多线程的存在,对于同一个变量可能存在两个或两个以上的线程同时修改变量所在的内存内容,同时又存在多个线程在变量在修改的时去读取该内存值,如果没有使用相应的同步机制来保护该内存的话,那么所读取到的数据将是不可预知的,甚至可能导致程序崩溃。
如果需要在一个线程内部的各个函数调用都能访问、但其它线程不能访问的变量,这就需要新的机制来实现,我们称之为Static memory local to a thread (线程局部静态变量),同时也可称之为线程特有数据(TSD: Thread-Specific Data)或者线程局部存储(TLS: Thread-Local Storage)。这一类型的数据,在程序中每个线程都会分别维护一份变量的副本(),并且长期存在于该线程中,对此类变量的操作不影响其他线程。如下图:

二、一次性初始化
在讲解线程特有数据之前,先让我们来了解一下一次性初始化。多线程程序有时有这样的需求:不管创建多少个线程,有些数据的初始化只能发生一次。列如:在C++程序中某个类在整个进程的生命周期内只能存在一个实例对象,在多线程的情况下,为了能让该对象能够安全的初始化,一次性初始化机制就显得尤为重要了。——在设计模式中这种实现常常被称之为单例模式(Singleton)。Linux中提供了如下函数来实现一次性初始化:
#include <pthread.h>

// Returns 0 on success, or a positive error number on error
int pthread_once (pthread_once_t *once_control, void (*init) (void));
利用参数once_control的状态,函数pthread_once()可以确保无论有多少个线程调用多少次该函数,也只会执行一次由init所指向的由调用者定义的函数。init所指向的函数没有任何参数,形式如下:
void init (void)
{
// some variables initializtion in here
}
另外,参数once_control必须是pthread_once_t类型变量的指针,指向初始化为PTHRAD_ONCE_INIT的静态变量。在C++0x以后提供了类似功能的函数std::call_once (),用法与该函数类似。使用实例请参考https://github.com/ApusApp/Swift/blob/master/swift/base/singleton.hpp实现。

⑧ c语言多线程编程问题

C语言中多线程的实现原理就是线程的原理,本人只了解Linux下面的C,linux下面的线程,不就是进程中的一个控制流么,相对来说代码很简单,但是原理却是很复杂,很难说清,还需要自己详细学习研究,下面是一个很简单的例子,哪边都能找到,自己运行下看看吧
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <string.h>
#define MAX 10
pthread_t thread[2];
pthread_mutex_t mut;
int number=0, i;
void *thread1()
{
printf ("thread1 : I'm thread 1\n");
for (i = 0; i < MAX; i++)
{
printf("thread1 : number = %d\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(2);
}
printf("thread1 :主函数在等我完成任务吗?\n");
pthread_exit(NULL);
}
void *thread2()
{
printf("thread2 : I'm thread 2\n");
for (i = 0; i < MAX; i++)
{
printf("thread2 : number = %d\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(3);
}
printf("thread2 :主函数在等我完成任务吗?\n");
pthread_exit(NULL);
}
void thread_create(void)
{
int temp;
memset(&thread, 0, sizeof(thread)); //comment1
/*创建线程*/
if((temp = pthread_create(&thread[0], NULL, thread1, NULL)) != 0) //comment2
printf("线程1创建失败!\n");
else
printf("线程1被创建\n");
if((temp = pthread_create(&thread[1], NULL, thread2, NULL)) != 0) //comment3
printf("线程2创建失败");
else
printf("线程2被创建\n");
}
void thread_wait(void)
{
/*等待线程结束*/
if(thread[0] !=0) { //comment4
pthread_join(thread[0],NULL);
printf("线程1已经结束\n");
}
if(thread[1] !=0) { //comment5
pthread_join(thread[1],NULL);
printf("线程2已经结束\n");
}
}
int main()
{
/*用默认属性初始化互斥锁*/
pthread_mutex_init(&mut,NULL);
printf("我是主函数哦,我正在创建线程,呵呵\n");
thread_create();
printf("我是主函数哦,我正在等待线程完成任务阿,呵呵\n");
thread_wait();
return 0;
}

⑨ linux下C多线程编程,为每个文件创建一个线程,转换内容大小写

你main里创建完线程就直接退出了,线程还没来的及干活就结束当然不行了。需要加pthread_join等待,像下面这样:
int main(int argc, char ** argv)
{
pthread_t tid[10];
int i;
for(i=1; i<argc; i++)
{
if(pthread_create(&tid[i], NULL, thr_convert, (void*)argv[i]) != 0)
{
perror("pthread_create");
exit(1);
}
}
for(i=1; i<argc; i++)
pthread_join(tid[i],NULL);

return EXIT_SUCCESS;
}

⑩ linux下C编程多线程同步和异步的区别,如何能实现程序的同步

同步和异步的区别:
1、同步就是说多个任务之间是有先后关系的,一个任务需要等待另一个任务执行完毕才能继续执行。
2、异步就是说多个任务之间没有先后关系,不需要相互等待各做各的事。
同步编程方法:
1、信号量
2、互斥量
异步无需考虑资源冲突,不需特别处理。

热点内容
mysql数据库编码修改 发布:2024-05-08 15:03:27 浏览:978
高斯混合模型的em算法 发布:2024-05-08 14:56:55 浏览:341
您访问过快 发布:2024-05-08 14:31:32 浏览:144
android广播生命周期 发布:2024-05-08 14:28:58 浏览:59
石器时代为什么没有安卓版 发布:2024-05-08 14:28:56 浏览:361
液晶电视换存储器 发布:2024-05-08 14:03:37 浏览:965
php交集 发布:2024-05-08 13:46:57 浏览:512
internet快速存储 发布:2024-05-08 13:26:50 浏览:978
编程代码基础 发布:2024-05-08 13:23:40 浏览:612
安卓手机用哪个手机稳定器 发布:2024-05-08 13:22:51 浏览:599