pro*c初学2---简单多线程例子
来源:互联网 发布:2018 专升本 网络教育 编辑:程序博客网 时间:2024/05/16 05:04
参考<<Proc*C/C++ Precompiler Programmer's Guide>> Release 8.1.6 ---Multithreaded Applications一章的例子写了个简单的多线程程序,书中例子似乎是针对linux环境的,需要pthread.h或thread.h两个头文件,但我电脑上的linux环境没有安装oracle,于是就仿照书中例子用VC做工具写了个简单的多线程的例子(windows多线程函数似乎和linux的多线程函数用法差别挺大),其实还有不少不懂的地方,而且现在也感受不到效率和并发问题。代码如下:
/*
* Name: proc_mul.pc
* 预编译条件: mode=ORACLE parse=FULL
* 利用多线程,更新表中记录;每个线程拥有单独的上下文环境
* 表结构: create table accounts (account number(36), balance(36,2))
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlca.h>
#include <windows.h>
#define CONNINFO "test/test"
#define THREADS 3
DWORD WINAPI do_transaction(); // 处理交易
void get_transaction(); // 获得记录
void logon();
void logoff();
void err_report(); // 错误处理
/*
* 记录线程id和运行时上下文的结构
*/
struct parameters
{
sql_context *ctx;
int thread_id;
};
typedef struct parameters parameters;
struct record_log
{
char action; // 操作类型
unsigned int from_account; // 出账号
unsigned int to_account; // 入账号
float amount; // 转账金额
};
typedef struct record_log record_log;
/**待更新数据记录**/
record_log records[] = {
{'M',10001,10008,10},
{'M',10002,10008,10},
{'M',10003,10008,10},
{'M',10004,10008,10},
{'M',10005,10008,10},
{'M',10006,10008,10},
{'M',10007,10008,10},
{'M',10001,10008,10},
{'M',10002,10008,10}
};
static unsigned int trx_nr = 0;
static unsigned int flag_over = 0;
HANDLE hMutex; // 定义互斥对象
/********主函数*************/
void main()
{
sql_context ctx[THREADS];
HANDLE thread_id[THREADS];
// int status;
parameters params[THREADS];
int i;
/*********支持多线程*********/
EXEC SQL ENABLE THREADS;
EXEC SQL WHENEVER SQLERROR DO err_report(sqlca);
/*create THEAD sessions by connect THREAD times*/
for(i = 0; i < THREADS; i++)
{
printf("start session %d.../n", i);
EXEC SQL CONTEXT ALLOCATE :ctx[i]; // 分配并初始化一块用于指向一个新的运行时上下文的内存
logon(ctx[i], CONNINFO);
}
/*创建互斥对象*/
hMutex = CreateMutex(NULL, FALSE, "trx_nr");
if(hMutex)
{
if(ERROR_ALREADY_EXISTS==GetLastError())
{
printf("only one instance can run...");
return;
}
}
/*创建线程*/
for(i = 0; i < THREADS; i++)
{
params[i].ctx = ctx[i];
params[i].thread_id = i;
thread_id[i] = CreateThread(NULL, 0, do_transaction, ¶ms[i], 0, &thread_id[i]);
CloseHandle(thread_id[i]);
}
/******利用一个全局变量判断所有线程是否结束********/
while(flag_over != THREADS)
{
Sleep(10000);
}
/***************有问题待查***************
//关闭线程及数据库连接
for(i = 0; i < THREADS; i++)
{
if(WaitForSingleObject(thread_id[i],0)==WAIT_OBJECT_0)
{
printf("test %d terminated/n", i);
printf("stop session %d.../n", i);
logoff(ctx[i]);
EXEC SQL CONTEXT FREE :ctx[i];
}
}
**************************************/
}
/*
* 数据处理函数,一次处理recors[]中的一条记录
* recors[]记录通过get_transaction()函数管理
*/
DWORD WINAPI do_transaction(parameters *params)
{
struct sqlca sqlca; // 局部通讯区
record_log *trx;
sql_context ctx = params->ctx;
/*处理数据,循环,知道records[]中数据被全部处理完*/
while(trx_nr < sizeof(records)/sizeof(record_log))
{
WaitForSingleObject(hMutex,INFINITE);
get_transaction(&trx); // 得到一条记录,需要用指针的地址
printf("thread %d is executing transaction.../n", params->thread_id);
ReleaseMutex(hMutex);
EXEC SQL WHENEVER SQLERROR DO err_report(sqlca);
EXEC SQL CONTEXT USE :ctx; // 每个线程具有独立的上下文环境
switch(trx->action)
{
case 'M':
EXEC SQL UPDATE ACCOUNT SET BALANCE=BALANCE+:trx->amount WHERE ACCOUNT=:trx->to_account;
EXEC SQL UPDATE ACCOUNT SET BALANCE=BALANCE-:trx->amount WHERE ACCOUNT=:trx->from_account;
break;
default:
break;
}
EXEC SQL COMMIT; // 事务提交
Sleep(2000);
}
/*线程结束,关闭数据库连接*/
printf("transaction finished, thread %d terminated/n", params->thread_id);
printf("stop session %d.../n", params->thread_id);
logoff(ctx);
EXEC SQL CONTEXT FREE :ctx; // 释放内存
flag_over++;
return 0;
}
/*
* 管理recors[]记录,控制并发
*/
void get_transaction(record_log **trx)
{
*trx = &records[trx_nr]; // 获得当前要处理的记录
trx_nr++;
}
/*
* 连接数据库
*/
void logon(sql_context ctx, char *connect_info)
{
EXEC SQL WHENEVER SQLERROR DO err_report(sqlca);
EXEC SQL CONTEXT USE :ctx;
EXEC SQL CONNECT :connect_info;
printf("connect.../n");
}
/*
* 断开数据库连接
*/
void logoff(sql_context ctx)
{
EXEC SQL WHENEVER SQLERROR DO err_report(sqlca);
EXEC SQL CONTEXT USE :ctx;
EXEC SQL COMMIT WORK RELEASE;
printf("logged off/n");
}
/*
* 错误处理函数
*/
void err_report(struct sqlca sqlca)
{
if(sqlca.sqlcode < 0)
{
printf("/n%.*s/n/n", sqlca.sqlerrm.sqlerrml,sqlca.sqlerrm.sqlerrmc);
exit(1);
}
}
在VC6.0环境下调试没问题,执行结果也正常。不过控制台的输出比较奇怪,有时候乱七八糟的,似乎在执行printf函数的时候出现了写问题,查了很久也不知道为什么。
- pro*c初学2---简单多线程例子
- 多线程 -- 初学简单例子
- Pro * C 简单例子
- Pro*c的简单例子
- 我写的简单的pro*c的例子
- 初学struts 2 , 配置及简单例子
- linux c最简单多线程例子:
- C/C++ 初学简单笔记 —6.1 — 多线程
- C/C++ 初学简单笔记 —6.2 — 多线程
- pro*C初学1---编译环境
- 关于使用PRO*C编程的一些简单说明和例子
- 关于使用PRO*C编程的一些简单说明和例子
- 关于使用PRO*C编程的一些简单说明和例子
- 关于使用PRO*C编程的一些简单说明和例子
- 关于使用PRO*C编程的一些简单说明和例子
- 关于使用PRO*C编程的一些简单说明和例子
- [C#] 一个简单的C#多线程间同步的例子
- Java 多线程 简单例子
- C++多态技术--荣耀
- C++多态技术的实现和反思
- j2me内存优化(新手必看)
- 上班族的痛!北京女孩挤城铁的经历
- 也写lcc源码分析(一)序
- pro*c初学2---简单多线程例子
- 童话的智慧
- P2P Information Community项目开发构想
- 软件开发者面试百问
- 2009出发啦
- google 惊天漏洞
- 历史性的时刻,google出问题了,全是恶意网站
- 全世界网站都可能含有恶意软件
- Windows XP 更新程序 (KB955704) 添加对exFAT文件系统格式的支持