ProC開發(fā)多線程應(yīng)用程序_第1頁
ProC開發(fā)多線程應(yīng)用程序_第2頁
ProC開發(fā)多線程應(yīng)用程序_第3頁
ProC開發(fā)多線程應(yīng)用程序_第4頁
ProC開發(fā)多線程應(yīng)用程序_第5頁
已閱讀5頁,還剩8頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

用Pro*C開發(fā)多線程應(yīng)用程序(注:本文來自Pro*C/C++PrecompilerProgrammer'sGuideRelease8.1.5)如果你的操作系統(tǒng)不支持線程,本文暫不適合你。本文包含以下幾個部分n什么是多線程?nPro*C中的運行時上下文n運行時上下文的使用模式n多線程應(yīng)用程序的用戶接口n多線程例子一.什么是多線程?一個多線程的應(yīng)用程序中,線程運行在共享的地址空間里。線程是在進程內(nèi)部執(zhí)行的“輕量”級子進程,它們共享代碼段和數(shù)據(jù)段,但是有自己的程序計數(shù)器、寄存器和堆棧。全局變量和靜態(tài)變量在線程之間是共享的,因此通常需要在程序中使用某種互斥機制來管理線程對這些變量的訪問,互斥體Mutexes就是用來保證數(shù)據(jù)完整性的同步裝置。有關(guān)互斥體的更多討論,參看多線程編程方面的文章。Proc*C編譯器通過以下方式支持開發(fā)多線程的Oracle應(yīng)用程序(在支持線程的平臺上):n用一個命令行編譯選項來產(chǎn)生線程安全的代碼n用內(nèi)嵌的SQL語句和指令支持多線程n線程安全的Lib庫和其他客戶端Lib庫注意:也許你的平臺支持某個特殊的線程包,但還是需要查看Oracle有關(guān)平臺的文檔,看看Oracle是否支持它。二.Pro*C中的運行時上下文為了在線程和數(shù)據(jù)庫連接之間建立松散的結(jié)合,Pro*C引入了一個概念runtime_context,我們稱之為運行時上下文。一個運行時上下文包含了以下資源和信息:n與數(shù)據(jù)庫服務(wù)器的連接n當前連接上使用的游標n內(nèi)嵌的一些選項,女口MODE,HOLD_CURSOR,RELEASE_CURSOR和SELECT_ERROR不僅僅是簡單的支持線程和連接之間的松散結(jié)合,Pro*C編譯器還允許開發(fā)人員在線程和運行時上下文之間建立松散的結(jié)合,Pro*C允許在程序里為運行時上下文定義一個句柄,通過這個句柄,運行時上下文可以在線程之間切換。例如,一個交互式應(yīng)用程序創(chuàng)建了線程T1,來執(zhí)行一個查詢,并且返回了前10條記錄,然后T1終止。在用戶輸入了必須的數(shù)據(jù)之后,程序又創(chuàng)建了線程T2,并且把T1使用的運行時上下文傳給T2,這樣T2可以在同一個游標上獲取接下來10條的記錄。三.運行時上下文的使用模式下面是在多線程的Pro*C程序中使用運行時上下文的兩種可能模式:n多線程共享單個運行時上下文n多線程使用互相獨立的運行時上下文不管采用哪種模式,不能在同一時刻多個線程共享同一個運行時上下文。如果兩個或兩個以上的線程在同一時刻試圖使用同一個運行時上下文,將會出現(xiàn)以下錯誤:SQL-02131:Runtimecontextinuse。1.多線程共享單個運行時上下文圖(一)展示了一個運行在多線程環(huán)境中的應(yīng)用程序,多個線程共享一個運行時上下文來執(zhí)行SQL語句,運行時上下文不能在同一時刻被多個線程使用,圖中的Mutex展示了如何防止這種并行使用。圖(一)2.多線程使用互相獨立的運行時上下文圖(二)展示了使用多個運行時上下文的多線程應(yīng)用程序,在這種情況下,程序不需要使用互斥鎖Mutex,因為每個線程擁有一個獨立的運行時上下文。圖(二)四.多線程應(yīng)用程序的用戶接口Pro*C編譯器提供以下接口來支持多線程:n命令行選項,THREADS=YES|NOn內(nèi)嵌SQL語句和指令n線程安全的公共庫函數(shù)1.THREADS選項在proc預(yù)編譯命令行上指定THREADS=YES,Pro*C編譯器將保證產(chǎn)生的C代碼是線程安全的。如果指定了THREADS=YES,Pro*C將會檢查每個包含SQL執(zhí)行語句的函數(shù),是否指定了這些語句是在哪個運行時上下文中執(zhí)行的,若沒有發(fā)現(xiàn)這類指定標識,編譯器就會返回錯誤。2.內(nèi)嵌SQL語句和指令F列內(nèi)嵌的SQL語句和指令用于支持多線程和運行時上下文的使用:nEXECSQLENABLETHREADS;nEXECSQLCONTEXTALLOCATE:context_var;nEXECSQLCONTEXTUSE{:context_var/DEFAULT};nEXECSQLCONTEXTFREE:context_var;在以上SQL語句中,context_var是運行時上下文句柄,它必須被定義成sql_context類型:如sql_contextcontext_var;使用DEFAULT意味著接下來的SQL語句將使用默認的全局運行時上下文,直到另一條CONTEXTUSE語句覆蓋它。nEXECSQLENABLETHREADS這條可執(zhí)行SQL語句初始化支持多線程的進程。它必須是程序中第一條可執(zhí)行的SQL語句。nEXECSQLCONTEXTALLOCATE這條可執(zhí)行SQL語句分配并初始化了一塊用于指向一個新的運行時上下文的內(nèi)存,并返回標識該上下文的句柄變量,該變量必須聲明為sql_context類型。nEXECSQLCONTEXTUSE這條指令性語句告訴編譯器接下去執(zhí)行的SQL語句將使用指定的運行時上下文,這里的運行時上下文必須在此前已經(jīng)用CONTEXTALLOCATE分配并初始化。nEXECSQLCONTEXTFREE這條語句釋放了運行時上下文句柄指定的內(nèi)存,并把它設(shè)置空值。3.編程時要考慮的問題盡管Oracle保證SQL庫是線程安全的,但是你還是有責任保證你的Pro*C代碼是為能在多線程下正確運行而設(shè)計的,例如,你必須考慮全局變量和靜態(tài)變量的。另外,多線程要求對以下問題進行考慮:n把sqlca結(jié)構(gòu)定義成線程安全的。典型的做法是在每個函數(shù)開始定義一個同名的局部變量。nsqlda結(jié)構(gòu)也和sqlca結(jié)構(gòu)一樣處理。n把程序里的宿主變量定義成線程安全的。也就是說要小心處理程序里的全局變量和靜態(tài)變量。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;/*創(chuàng)建兩個線程*/if(pthread_create(&tid1,NULL,(void*)start,NULL)){printf("創(chuàng)建線程失敗!\n");exit(1);}if(pthread_create(&tid2,NULL,(void*)start,NULL)){printf("創(chuàng)建線程失敗!\n");exit(1);}/*等待線程退出*/if(pthread_join(tid1,NULL)){printf("等待線程結(jié)束失敗!\n");exit(1);}if(pthread_join(tid2,NULL)){printf("等待線程結(jié)束失敗!\n");exit(1);}exit(0);intstart(){sql_contextcontext;structsqlcasqlca;/*需要在此定義一個局部的sqlca*/charuid[]="dev/888888";/*以下SQL語句的執(zhí)行順序不能更改*/EXECSQLENABLETHREADS;EXECSQLCONTEXTALLOCATE:context;EXECSQLCONTEXTUSE:context;EXECSQLCONNECT:uid;if(SQLCODE<0){printf("創(chuàng)建數(shù)據(jù)庫連接失敗,%d:%s\n",SQLCODE,sqlca.sqlerrm.sqlerrmc);return-1;}insert_data(context);EXECSQLCOMMITWORKRELEASE;if(SQLCODE<0){printf("斷開數(shù)據(jù)庫連接失敗!%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;/*指定執(zhí)行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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論