線程是任務調度的基本單位,一個進程中能夠有多個線程,每一個線程有本身的堆棧空間,
進程中的代碼段、數據段和堆棧對進程中的線程是可見的。在使用線程時一般都要考慮數據的安全訪問。
經常使用的線程同步方法有: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); }