ProC开发多线程应用程序_第1页
ProC开发多线程应用程序_第2页
ProC开发多线程应用程序_第3页
ProC开发多线程应用程序_第4页
ProC开发多线程应用程序_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

用Pro*C开发多线程应用程序(注:本文来自Pro*C/C++PrecompilerProgrammer'sGuideRelease8.1.5)如果你的操作系统不支持线程,本文暂不适合你。本文包含以下几个部分n什么是多线程?nPro*C中的运行时上下文n运行时上下文的使用模式n多线程应用程序的用户接口n多线程例子一.什么是多线程?一个多线程的应用程序中,线程运行在共享的地址空间里。线程是在进程内部执行的“轻量”级子进程,它们共享代码段和数据段,但是有自己的程序计数器、寄存器和堆栈。全局变量和静态变量在线程之间是共享的,因此通常需要在程序中使用某种互斥机制来管理线程对这些变量的访问,互斥体Mutexes就是用来保证数据完整性的同步装置。有关互斥体的更多讨论,参看多线程编程方面的文章。Proc*C编译器通过以下方式支持开发多线程的Oracle应用程序(在支持线程的平台上):n用一个命令行编译选项来产生线程安全的代码n用内嵌的SQL语句和指令支持多线程n线程安全的Lib库和其他客户端Lib库注意:也许你的平台支持某个特殊的线程包,但还是需要查看Oracle有关平台的文档,看看Oracle是否支持它。二.Pro*C中的运行时上下文为了在线程和数据库连接之间建立松散的结合,Pro*C引入了一个概念runtime_context,我们称之为运行时上下文。一个运行时上下文包含了以下资源和信息:n与数据库服务器的连接n当前连接上使用的游标n内嵌的一些选项,女口MODE,HOLD_CURSOR,RELEASE_CURSOR和SELECT_ERROR不仅仅是简单的支持线程和连接之间的松散结合,Pro*C编译器还允许开发人员在线程和运行时上下文之间建立松散的结合,Pro*C允许在程序里为运行时上下文定义一个句柄,通过这个句柄,运行时上下文可以在线程之间切换。例如,一个交互式应用程序创建了线程T1,来执行一个查询,并且返回了前10条记录,然后T1终止。在用户输入了必须的数据之后,程序又创建了线程T2,并且把T1使用的运行时上下文传给T2,这样T2可以在同一个游标上获取接下来10条的记录。三.运行时上下文的使用模式下面是在多线程的Pro*C程序中使用运行时上下文的两种可能模式:n多线程共享单个运行时上下文n多线程使用互相独立的运行时上下文不管采用哪种模式,不能在同一时刻多个线程共享同一个运行时上下文。如果两个或两个以上的线程在同一时刻试图使用同一个运行时上下文,将会出现以下错误:SQL-02131:Runtimecontextinuse。1.多线程共享单个运行时上下文图(一)展示了一个运行在多线程环境中的应用程序,多个线程共享一个运行时上下文来执行SQL语句,运行时上下文不能在同一时刻被多个线程使用,图中的Mutex展示了如何防止这种并行使用。图(一)2.多线程使用互相独立的运行时上下文图(二)展示了使用多个运行时上下文的多线程应用程序,在这种情况下,程序不需要使用互斥锁Mutex,因为每个线程拥有一个独立的运行时上下文。图(二)四.多线程应用程序的用户接口Pro*C编译器提供以下接口来支持多线程:n命令行选项,THREADS=YES|NOn内嵌SQL语句和指令n线程安全的公共库函数1.THREADS选项在proc预编译命令行上指定THREADS=YES,Pro*C编译器将保证产生的C代码是线程安全的。如果指定了THREADS=YES,Pro*C将会检查每个包含SQL执行语句的函数,是否指定了这些语句是在哪个运行时上下文中执行的,若没有发现这类指定标识,编译器就会返回错误。2.内嵌SQL语句和指令F列内嵌的SQL语句和指令用于支持多线程和运行时上下文的使用:nEXECSQLENABLETHREADS;nEXECSQLCONTEXTALLOCATE:context_var;nEXECSQLCONTEXTUSE{:context_var/DEFAULT};nEXECSQLCONTEXTFREE:context_var;在以上SQL语句中,context_var是运行时上下文句柄,它必须被定义成sql_context类型:如sql_contextcontext_var;使用DEFAULT意味着接下来的SQL语句将使用默认的全局运行时上下文,直到另一条CONTEXTUSE语句覆盖它。nEXECSQLENABLETHREADS这条可执行SQL语句初始化支持多线程的进程。它必须是程序中第一条可执行的SQL语句。nEXECSQLCONTEXTALLOCATE这条可执行SQL语句分配并初始化了一块用于指向一个新的运行时上下文的内存,并返回标识该上下文的句柄变量,该变量必须声明为sql_context类型。nEXECSQLCONTEXTUSE这条指令性语句告诉编译器接下去执行的SQL语句将使用指定的运行时上下文,这里的运行时上下文必须在此前已经用CONTEXTALLOCATE分配并初始化。nEXECSQLCONTEXTFREE这条语句释放了运行时上下文句柄指定的内存,并把它设置空值。3.编程时要考虑的问题尽管Oracle保证SQL库是线程安全的,但是你还是有责任保证你的Pro*C代码是为能在多线程下正确运行而设计的,例如,你必须考虑全局变量和静态变量的。另外,多线程要求对以下问题进行考虑:n把sqlca结构定义成线程安全的。典型的做法是在每个函数开始定义一个同名的局部变量。nsqlda结构也和sqlca结构一样处理。n把程序里的宿主变量定义成线程安全的。也就是说要小心处理程序里的全局变量和静态变量。n避免同一时刻不同线程使用同一个运行时上下文。五.多线程例子下面的例子运行在RedHat9和Oracle9上。程序目的是用两个线程同时往一个表里插10000条记录,每个线程都拥有自己的运行时上下文。#include<stdio.h>;#include<unistd.h>;#include<pthread.h>;/*Linux线程库头文件*/#include"sqlca.h"/*Oracle头文件*/#defineSQLCODEsqlca.sqlcodestaticintinsert_data(sql_context);staticintstart();intmain(){pthread_ttid1,tid2;/*创建两个线程*/if(pthread_create(&tid1,NULL,(void*)start,NULL)){printf("创建线程失败!\n");exit(1);}if(pthread_create(&tid2,NULL,(void*)start,NULL)){printf("创建线程失败!\n");exit(1);}/*等待线程退出*/if(pthread_join(tid1,NULL)){printf("等待线程结束失败!\n");exit(1);}if(pthread_join(tid2,NULL)){printf("等待线程结束失败!\n");exit(1);}exit(0);intstart(){sql_contextcontext;structsqlcasqlca;/*需要在此定义一个局部的sqlca*/charuid[]="dev/888888";/*以下SQL语句的执行顺序不能更改*/EXECSQLENABLETHREADS;EXECSQLCONTEXTALLOCATE:context;EXECSQLCONTEXTUSE:context;EXECSQLCONNECT:uid;if(SQLCODE<0){printf("创建数据库连接失败,%d:%s\n",SQLCODE,sqlca.sqlerrm.sqlerrmc);return-1;}insert_data(context);EXECSQLCOMMITWORKRELEASE;if(SQLCODE<0){printf("断开数据库连接失败!%d:%s\n",SQLCODE,sqlca.sqlerrm.sqlerrmc);return-1;EXECSQLCONTEXTFREE:context;return0;}staticintinsert_data(context)sql_contextcontext;{structsqlcasqlca;/*需要在此定义一个局部的sqlca*/charname[11];intage;inti;strcpy(name,"test");age=20;EXECSQLCONTEXTUSE:context;/*指定执行SQL语句的上下文*/for(i=0;i<10000;i++){EXECSQLINSERTINTOtable1VALUES(:name,:age);if(SQLCODE<0){printf("插入纪录失败!%d:%s\n",SQLCODE,sqlca.sqlerrm.sqlerrmc);return-1;}}return0;///////////////////////////////////////////////////////////////////////////////////////在main中进行context的初始化//////////////////////////////////////////////////////////////////////////////////#include<windows.h>#include<stdio.h>#include<string.h>#include<stdlib.h>#include<sqlca.h>#include<sqlda.h>#include<process.h>typedefunsigned(WINAPI*PBEGINTHREADEX_THREADFUNC)(LPVOIDlpThreadParameter);typedefunsigned*PBEGINTHREADEX_THREADID;EXECSQLBEGINDECLARESECTION;#defineTHREADS2structparameters{sql_context*ctx;intthread_id;};typedefstructparametersparameters;charusername[20],password[20],server[20];EXECSQLENDDECLARESECTION;voidsql_error(structsqlca);voidlogon(sql_context);voidlogoff(sql_context);voidquery1(parameters*);voidquery2(parameters*);voidmain(intargc,char**argv){EXECSQLBEGINDECLARESECTION;sql_contextctx[THREADS];EXECSQLENDDECLARESECTION;HANDLEthread[THREADS];DWORDthreadid[THREADS];parametersparams[THREADS];inti;char*connstr,*pos;connstr=(char*)malloc(sizeof(char)*(strlen(argv[1])+1));strcpy(connstr,argv[1]);if(pos=strchr(connstr,'/')){connstr[pos-connstr]='\0';strcpy(username,connstr);connstr=pos+1;}if(pos=strchr(connstr,'@')){connstr[pos-connstr]='\0';strcpy(password,connstr);connstr=pos+1;}strcpy(server,connstr);EXECSQLENABLETHREADS;EXECSQLWHENEVERSQLERRORDOsql_error(sqlca);for(i=0;i<THREADS;i++){printf("startthread%d\n",i+1);EXECSQLCONTEXTALLOCATE:ctx[i];logon(ctx[i]);}for(i=0;i<THREADS;i++){params[i].ctx=ctx[i];params[i].thread_id=i;switch(i){case0:thread[i]=(HANDLE)_beginthreadex(NULL,0,(PBEGINTHREADEX_THREADFUNC)query1,¶ms[i],0,(PBEGINTHREADEX_THREADID)&threadid[i]);printf("%dthreadstart\n",i+1);break;case1:thread[i]=(HANDLE)_beginthreadex(NULL,0,(PBEGINTHREADEX_THREADFUNC)query2,¶ms[i],0,(PBEGINTHREADEX_THREADID)&threadid[i]);printf("No.%dthreadstart\n",i+1);break;}}for(i=0;i<THREADS;i++){DWORDdwRet=WaitForMultipleObjects(THREADS,thread,TRUE,INFINITE);logoff(ctx[i]);EXECSQLCONTEXTFREE:ctx[i];}}voidquery1(parameters*param){structsqlcasqlca;EXECSQLBEGINDECLARESECTION;longart_no;chardescr[33];EXECSQLENDDECLARESECTION;sql_contextctx;ctx=param->ctx;EXECSQLWHENEVERSQLERRORDOsql_error(sqlca);EXECSQLCONTEXTUSE:ctx;EXECSQLselectart_no,descrinto:art_no,:descrfromarticlewhereart_no=10;printf("%d%s\n",art_no,descr);}voidquery2(parameters*param){structsqlcasqlca;EXECSQLBEGINDECLARESECTION;longart_no;chardescr[33];EXECSQLENDDECLARESECTION;sql_contextctx;ctx=param->ctx;EXECSQLWHENEVERSQL

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论