OCCI線程安全

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

  • 互斥變量
  • 讀寫鎖
  • 條件變量
  • 屏障
  • 自旋鎖(用於CPU,鎖住後CPU將不執行其餘事情,即一直等待)

在OCCI程序中使能線程安全,則應指定THREADED_MUTEXED選項建立運行環境c++

例如:
    Environment *env =
         Environment::createEnvironment(Environment::THREADED_MUTEXED)

注意:sql

  • 若是應用程序是單線程,則使用默認值建立環境便可;
    若是指定THREADED_MUTEXED選項建立將會影響應用程序性能。
  • OCCI中的線程安全僅僅指的是EnvironmentMapConnectionPool
    StatelessConnectionPoolConnection對象。對於StatementResultSet
    SQLExceptionStream等不是線程安全的,所以不該該在多個線程中共享。

如下例子建立一個只有一個鏈接的無狀態鏈接池,建立兩個線程去競爭從池中獲得鏈接
當以線程安全建立環境時程序運行正常,當使用默認選項建立環境時,程序將拋出異常: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);
}
相關文章
相關標籤/搜索