OCCI线程安全

线程是任务调度的基本单位,一个进程中可以有多个线程,每个线程有自己的堆栈空间,
进程中的代码段、数据段和堆栈对进程中的线程是可见的。在使用线程时通常都要考虑数据的安全访问。
常用的线程同步方法有:

  • 互斥变量
  • 读写锁
  • 条件变量
  • 屏障
  • 自旋锁(用于CPU,锁住后CPU将不执行其他事情,即一直等待)

在OCCI程序中使能线程安全,则应指定THREADED_MUTEXED选项创建运行环境

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

注意:

  • 如果应用程序是单线程,则使用默认值创建环境即可;
    如果指定THREADED_MUTEXED选项创建将会影响应用程序性能。
  • OCCI中的线程安全仅仅指的是EnvironmentMapConnectionPool
    StatelessConnectionPoolConnection对象。对于StatementResultSet
    SQLExceptionStream等不是线程安全的,因此不应该在多个线程中共享。

以下例子创建一个只有一个连接的无状态连接池,创建两个线程去竞争从池中得到连接
当以线程安全创建环境时程序运行正常,当使用默认选项创建环境时,程序将抛出异常:

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);
}

猜你喜欢

转载自www.cnblogs.com/Focus-Flying/p/9283104.html