用Pro*C开发多线程应用程序
(注:本文来自Pro*C/C++ Precompiler Programmer's Guide Release 8.1.5)
|
|
|||
n 什么是多线程?
n Pro*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: Runtime context in use。
1.多线程共享单个运行时上下文
图(一)展示了一个运行在多线程环境中的应用程序,多个线程共享一个运行时上下文来执行SQL语句,运行时上下文不能在同一时刻被多个线程使用,图中的Mutex展示了如何防止这种并行使用。
图(一)
2.多线程使用互相独立的运行时上下文
图(二)展示了使用多个运行时上下文的多线程应用程序,在这种情况下,程序不需要使用互斥锁Mutex,因为每个线程拥有一个独立的运行时上下文。
图(二)
四.多线程应用程序的用户接口
Pro*C编译器提供以下接口来支持多线程:
n 命令行选项,THREADS=YES|NO
n 内嵌SQL语句和指令
n 线程安全的公共库函数
1.THREADS选项
在proc预编译命令行上指定THREADS=YES,Pro*C编译器将保证产生的C代码是线程安全的。如果指定了THREADS=YES,Pro*C将会检查每个包含SQL执行语句的函数,是否指定了这些语句是在哪个运行时上下文中执行的,若没有发现这类指定标识,编译器就会返回错误。
2.内嵌SQL语句和指令
下列内嵌的SQL语句和指令用于支持多线程和运行时上下文的使用:
n EXEC SQL ENABLE THREADS;
n EXEC SQL CONTEXT ALLOCATE :context_var;
n EXEC SQL CONTEXT USE {:context_var/DEFAULT};
n EXEC SQL CONTEXT FREE :context_var;
在以上SQL语句中,context_var是运行时上下文句柄,它必须被定义成sql_context类型:如sql_context context_var;
使用DEFAULT意味着接下来的SQL语句将使用默认的全局运行时上下文,直到另一条CONTEXT USE语句覆盖它。
n EXEC SQL ENABLE THREADS
这条可执行SQL语句初始化支持多线程的进程。它必须是程序中第一条可执行的SQL语句。
n EXEC SQL CONTEXT ALLOCATE
这条可执行SQL语句分配并初始化了一块用于指向一个新的运行时上下文的内存,并返回标识该上下文的句柄变量,该变量必须声明为sql_context类型。
n EXEC SQL CONTEXT USE
这条指令性语句告诉编译器接下去执行的SQL语句将使用指定的运行时上下文,这里的运行时上下文必须在此前已经用CONTEXT ALLOCATE分配并初始化。
n EXEC SQL CONTEXT FREE
这条语句释放了运行时上下文句柄指定的内存,并把它设置空值。
3.编程时要考虑的问题
尽管Oracle保证SQL库是线程安全的,但是你还是有责任保证你的Pro*C代码是为能在多线程下正确运行而设计的,例如,你必须考虑全局变量和静态变量的。
另外,多线程要求对以下问题进行考虑:
n 把sqlca结构定义成线程安全的。典型的做法是在每个函数开始定义一个同名的局部变量。
n sqlda结构也和sqlca结构一样处理。
n 把程序里的宿主变量定义成线程安全的。也就是说要小心处理程序里的全局变量和静态变量。
n 避免同一时刻不同线程使用同一个运行时上下文。
五.多线程例子
下面的例子运行在Red Hat9和Oracle9上。程序目的是用两个线程同时往一个表里插10000条记录,每个线程都拥有自己的运行时上下文。
#include<stdio.h>
#include<unistd.h>
#include<pthread.h> /* Linux线程库头文件 */
#include "sqlca.h" /* Oracle头文件 */
#define SQLCODE sqlca.sqlcode
static int insert_data( sql_context );
static int start();
int
main()
{
pthread_t tid1, 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);
}
int
start()
{
sql_context context;
struct sqlca sqlca; /* 需要在此定义一个局部的sqlca */
char uid[] = "dev/888888";
/* 以下SQL语句的执行顺序不能更改 */
EXEC SQL ENABLE THREADS;
EXEC SQL CONTEXT ALLOCATE :context;
EXEC SQL CONTEXT USE :context;
EXEC SQL CONNECT :uid;
if( SQLCODE < 0 ){
printf( "创建数据库连接失败,%d:%s\n", SQLCODE,sqlca.sqlerrm.sqlerrmc);
return -1;
}insert_data( context );
EXEC SQL COMMIT WORK RELEASE;
if( SQLCODE < 0 ){
printf( "断开数据库连接失败!%d:%s\n", SQLCODE,sqlca.sqlerrm.sqlerrmc );
return -1;
}
EXEC SQL CONTEXT FREE :context;
return 0;
}
static int
insert_data( context )
sql_context context;
{
struct sqlca sqlca; /* 需要在此定义一个局部的sqlca */
char name[11];
int age;
int i;
strcpy( name, "test" );
age = 20;
EXEC SQL CONTEXT USE :context; /* 指定执行SQL语句的上下文 */
for( i=0; i<10000; i++ ){
EXEC SQL INSERT INTO table1 VALUES ( :name, :age );
if( SQLCODE < 0 ){
printf( "插入纪录失败!%d:%s\n", SQLCODE, sqlca.sqlerrm.sqlerrmc );
return -1;
}
}
return 0;
}
本论坛有
[url]http://bbs.chinaunix.net/forum/47/20031216/223940.html[/url]
相关图文阅读
频道图文推荐
相关专题
·oltp系统,数据块大小用4k还是8k好? (0次浏览)
·在RHEL4U4上安装Oracle10GS2 (0次浏览)
·如何在Python下连接Oracle数据库 (0次浏览)
·Oracle中对COLUMNS_UPDATED()返回值解析 (0次浏览)
·Oracle 容灾复制解决方案分析Shar Plex (0次浏览)
·简述数据库导入Oracle SQL*Loader指南 (0次浏览)
·详细解述oracle数据库九个基本操作 (0次浏览)
·Oracle数据库Lite 10g第三版面市 (0次浏览)
·如何避免Oracle数据库密码出现@符号 (0次浏览)
·在Oracle中使用登录触发器初始化用户会话 (0次浏览)
·在RHEL4U4上安装Oracle10GS2 (0次浏览)
·如何在Python下连接Oracle数据库 (0次浏览)
·Oracle中对COLUMNS_UPDATED()返回值解析 (0次浏览)
·Oracle 容灾复制解决方案分析Shar Plex (0次浏览)
·简述数据库导入Oracle SQL*Loader指南 (0次浏览)
·详细解述oracle数据库九个基本操作 (0次浏览)
·Oracle数据库Lite 10g第三版面市 (0次浏览)
·如何避免Oracle数据库密码出现@符号 (0次浏览)
·在Oracle中使用登录触发器初始化用户会话 (0次浏览)
·ORACLE的客户端如何连接到数据库 (127次浏览)
·八个学习点帮助你全面认识Oracle数据库 (91次浏览)
·oracle自定义函数的执行时间 (71次浏览)
·利用Oracle管理服务器将数据导入导出 (45次浏览)
·了解Oracle存储过程中的角色 (44次浏览)
·Oracle-Decode()函数和CASE语句的比较 (18次浏览)
·如何使用Logmnr方法分析数据库日志 (18次浏览)
·Oracle9i数据挖掘介绍 (16次浏览)
·Linux 9i下Dataguard配置 (14次浏览)
·ORACLE 截断字符串 (13次浏览)
·八个学习点帮助你全面认识Oracle数据库 (91次浏览)
·oracle自定义函数的执行时间 (71次浏览)
·利用Oracle管理服务器将数据导入导出 (45次浏览)
·了解Oracle存储过程中的角色 (44次浏览)
·Oracle-Decode()函数和CASE语句的比较 (18次浏览)
·如何使用Logmnr方法分析数据库日志 (18次浏览)
·Oracle9i数据挖掘介绍 (16次浏览)
·Linux 9i下Dataguard配置 (14次浏览)
·ORACLE 截断字符串 (13次浏览)
·Oracle的初学者入门心得 (588次浏览)
·Oracle SQL性能优化技巧大总结 (461次浏览)
·ORACLE内置函数大全 (335次浏览)
·Oracle DBA数据库日常维护完全手册 (294次浏览)
·用ORACLE数据库存储海量图像数据 (286次浏览)
·Oracle体系结构:内存结构和进程结构 (248次浏览)
·开启企业殿堂的钥匙 Oracle服务器的安装 (185次浏览)
·将Oracle的数据导入EXCEL中的方法 (167次浏览)
·简单冷备份恢复操作步骤 (130次浏览)
·oracle下导出某用户所有表的方法 (128次浏览)
·Oracle SQL性能优化技巧大总结 (461次浏览)
·ORACLE内置函数大全 (335次浏览)
·Oracle DBA数据库日常维护完全手册 (294次浏览)
·用ORACLE数据库存储海量图像数据 (286次浏览)
·Oracle体系结构:内存结构和进程结构 (248次浏览)
·开启企业殿堂的钥匙 Oracle服务器的安装 (185次浏览)
·将Oracle的数据导入EXCEL中的方法 (167次浏览)
·简单冷备份恢复操作步骤 (130次浏览)
·oracle下导出某用户所有表的方法 (128次浏览)
最新技术文档
·Oracle Lite 10g数据库第三版正式问世 06-25
·Oracle 动态SQL返回单条结果和结果集 06-25
·Oracle多行记录字符串综合操作几种方法 06-24
·如何通过实例配置Oracle监听器 06-24
·Oracle数据库中LONG类型字段的存取 06-24
·介绍几个基本的 SQLPLUS 命令 06-22
·与数据库无关的处理放到数据库以外来实现 06-22
·简析Oracle数据库最大可用性体系结构 06-22
·数据库开发者常犯的十大错误,你有吗? 06-21
·Oracle数据复制技术有效解决数据冗余 06-21
·Oracle 动态SQL返回单条结果和结果集 06-25
·Oracle多行记录字符串综合操作几种方法 06-24
·如何通过实例配置Oracle监听器 06-24
·Oracle数据库中LONG类型字段的存取 06-24
·介绍几个基本的 SQLPLUS 命令 06-22
·与数据库无关的处理放到数据库以外来实现 06-22
·简析Oracle数据库最大可用性体系结构 06-22
·数据库开发者常犯的十大错误,你有吗? 06-21
·Oracle数据复制技术有效解决数据冗余 06-21
站内各频道最新更新文档
站内最新制作专题
|
|||
| ·ACDSEE专题教程-下载使用 ·迅雷专题教程-下载使用 ·Windows XP频道 ·Windows Vista频道 ·Windows 2000频道 ·win2003频道 ·Freebsd频道 ·Oracle频道 |
·Linux频道 ·Windows频道 ·邮件服务器专题 ·协议大全 ·数据恢复指南教程 ·FreeBSD使用教程 ·Linux数据库宝典 ·Linux基础知识 |
||
热门关键字导读
站内频道文章精选
| · 秘密:Vista隐蔽的动态屏保 · 腾讯开发新电子宠物--QQ熊 · 惠普否认2999元PC有价无货 |
· 驱逐Win系统“流氓”文件 · WinXP中获取未使用的IP地址 · 尝试format C:格式化硬盘? |
| · 在DOS下恢复回收站中的文件 · 拯救WinXP崩溃的救命稻草 · Linux系统中超级权限的应用 |
· 搜狗PK谷歌:谁能代言拼... · 昨日重现,一键GHOST轻松.. · 实现Web迅雷在空闲时杀毒 |
| · AVIFile函数制做AVI文件 · VC中链接动态链接库的方法 · 熊猫烧香核心源码(Delphi) |
· DateDiff函数祥解 · JavaScript去除空格的三种 · js效果 图片加载进度实时.. |
| · SQL Server数据库优化方案 · Oracle的初学者入门心得 · JSP连接Mysql数据库 |
· Photoshop为美女做艺术处理 · 用Freehand创建发光字特效 · 设计自己的个性QQ动态表情 |
百度推荐,商机无限
搜索您感兴趣的内容




