线程是任务调度的基本单位,一个进程中能够有多个线程,每一个线程有本身的堆栈空间,
进程中的代码段、数据段和堆栈对进程中的线程是可见的。在使用线程时一般都要考虑数据的安全访问。
经常使用的线程同步方法有:ios
- 互斥变量
- 读写锁
- 条件变量
- 屏障
- 自旋锁(用于CPU,锁住后CPU将不执行其余事情,即一直等待)
在OCCI程序中使能线程安全,则应指定THREADED_MUTEXED
选项建立运行环境c++
例如: Environment *env = Environment::createEnvironment(Environment::THREADED_MUTEXED)
注意:sql
- 若是应用程序是单线程,则使用默认值建立环境便可;
若是指定THREADED_MUTEXED
选项建立将会影响应用程序性能。- OCCI中的线程安全仅仅指的是
Environment
、Map
、ConnectionPool
、
StatelessConnectionPool
和Connection
对象。对于Statement
、ResultSet
、
SQLException
、Stream
等不是线程安全的,所以不该该在多个线程中共享。
如下例子建立一个只有一个链接的无状态链接池,建立两个线程去竞争从池中获得链接
当以线程安全建立环境时程序运行正常,当使用默认选项建立环境时,程序将抛出异常:shell
what(): ORA-03117: two-task save area overflow
#include <iostream> #include <cstdlib> #include <pthread.h> #include <unistd.h> #include <occi.h> #define USERNAME "scott" #define PASSWORD "scott" #define DBNAME "//192.168.42.135:1521/orcl" #define MAXCON 1 #define MINCON 0 #define INCCON 1 using namespace oracle::occi; using namespace std; void *displayAllRows(void *arg); void *updateRow(void *arg); int main(void) { Environment *env = Environment::createEnvironment(Environment::THREADED_MUTEXED); //建立无状态链接池 StatelessConnectionPool *scp = env->createStatelessConnectionPool( USERNAME, PASSWORD, DBNAME, MAXCON, MINCON, INCCON, StatelessConnectionPool::HOMOGENEOUS); //设置池中的链接空闲超时时间,超时后OCCI会自动释放此链接,须要时在建立 scp->setTimeOut(10); cout << "*****************Information**************************" << endl; cout << "Open Connection : " << scp->getOpenConnections() << endl; cout << "Busy Connection : " << scp->getBusyConnections() << endl; cout << "Time Out Connection : " << scp->getTimeOut() << endl; cout << "******************************************************" << endl; pthread_t tid_1, tid_2; int err = 0; err = pthread_create(&tid_1, NULL, displayAllRows, (void *)scp); if (err != 0) { cout << "create thread failure for tid_1." << endl; } else { cout << ">> create thread successful for tid_1." << endl; } err = pthread_create(&tid_2, NULL, updateRow, (void *)scp); if (err != 0) { cout << "create thread failure for tid_2." << endl; } else { cout << ">> create thread successful for tid_2." << endl; } pthread_join(tid_1, (void **)NULL); pthread_join(tid_2, (void **)NULL); env->terminateStatelessConnectionPool(scp); Environment::terminateEnvironment(env); return 0; } void *displayAllRows(void *arg) { StatelessConnectionPool *scp = (StatelessConnectionPool *)arg; for ( ; ; ) { std::cout << ">>>> displayAllRows thread runing [" << long(pthread_self()) << "]" << std::endl; Connection *conn = scp->getConnection(""); string sqlStmt = "SELECT * FROM DEPT WHERE DEPTNO=60"; Statement *stmt = conn->createStatement(sqlStmt); ResultSet *rset = stmt->executeQuery(); try { while (rset->next()) { cout << int(rset->getNumber(1)) << " "; cout << rset->getString(2) << " "; cout << rset->getString(3) << " "; cout << endl; } }catch(SQLException &ex) { cout << "display all rows failure." << endl; cout << ex.getMessage(); cout << endl; } sleep(5); stmt->closeResultSet(rset); conn->terminateStatement(stmt); scp->releaseConnection(conn, ""); } pthread_exit((void *)0); } void *updateRow(void *arg) { StatelessConnectionPool *scp = (StatelessConnectionPool*)arg; for ( ; ; ) { std::cout << ">>> updateRow thread running [" << long(pthread_self()) << "]" << std::endl; Connection *conn = scp->getConnection(""); string sqlStmt = "UPDATE DEPT SET LOC=:deptLocal WHERE DEPTNO=51"; Statement *stmt = conn->createStatement(sqlStmt); try { stmt->setString(1, "ShangHai"); stmt->executeUpdate(); conn->commit(); } catch(SQLException &ex) { cout << "update row failure." << endl; cout << ex.getMessage(); cout << endl; } conn->terminateStatement(stmt); scp->releaseConnection(conn, ""); sleep(1); } pthread_exit((void *)0); }