c++ std::lock_guard/unique_lock

1. std::lock_guard

c++11引入的类模板,用于取代lock和unlock;

template<typename _Mutex>
class lock_guard
{
public:
    typedef _Mutex mutex_type;

    //构造自动加锁
    explicit lock_guard(mutex_type& __m) : _M_device(__m)
    { _M_device.lock(); }
    
    lock_guard(mutex_type& __m, adopt_lock_t) noexcept : _M_device(__m)
    { } // calling thread owns mutex
    
    //析构自动解锁
    ~lock_guard()
    { _M_device.unlock(); }
    
    lock_guard(const lock_guard&) = delete;
    lock_guard& operator=(const lock_guard&) = delete;

private:
    mutex_type&  _M_device;
};

 原理: 构造自动加锁,析构自动解锁;离开作用域时调用析构自动解锁

{
    std::lock_guard<std::mutex> lock(mtx);
    // 临界区代码
} // 自动解锁

2. std::unique_lock

类模板,功能与lock_guard类似,但比lock_guard灵活;unique_lock可以完全取代lock_guard,

        std::unique_lock<std::mutex> t_lock(mutex);

unique_lock还存在第二参数,可灵活配置;

2.1 adopt_lock

lock_guard和unique_lock都可以带第二个参数std::adopt_lock;

它表示这个互斥量已经被锁定了,锁定对象在构造时不会尝试锁定互斥量,而是"收养"已存在的锁;

这种策略通常用于管理已经锁定的互斥量;

场景1: 
{
    g_mutex.lock(); //加锁
    //std::unique_lock<std::mutex> t_lock1(g_mutex, std::adopt_lock);

    //不带 std::adopt_lock参数,则构造函数会加锁,而上面已经加锁,那么这里会导致死锁;
    std::unique_lock<std::mutex> t_lock1(g_mutex);
}

场景2: 
{
    g_mutex.lock(); //加锁

    //带 std::adopt_lock参数,构造函数不会加锁,一切正常
    std::unique_lock<std::mutex> t_lock1(g_mutex, std::adopt_lock);

    //std::unique_lock<std::mutex> t_lock1(g_mutex);
}

场景3: 
{
    //g_mutex.lock(); 

    //带 std::adopt_lock参数,构造函数不会加锁; 而前面没有lock,后续的代码可能存在风险!!!
    std::unique_lock<std::mutex> t_lock1(g_mutex, std::adopt_lock);

    //std::unique_lock<std::mutex> t_lock1(g_mutex);
}

 总结: 使用std::adopt_lock的前提是开发者需要先把互斥量lock上。

2.2 try_to_lock

系统尝试去lock这个mutex;没锁成功,也会立即返回,并不会阻塞

场景1:
{
    //g_mutex.lock();
    std::unique_lock<std::mutex> t_lock1(g_mutex, std::try_to_lock);
    if(t_lock1.owns_lock()){
        //打印
        std::cout << "Lock acquire ok" << std::endl;
    }else{
        std::cout << "timeout failed to acquire lock" << std::endl;
    }
}

场景2:
{
    g_mutex.lock();
    std::unique_lock<std::mutex> t_lock1(g_mutex, std::try_to_lock);
    if(t_lock1.owns_lock()){
        std::cout << "Lock acquire ok" << std::endl;
    }else{
        //打印
        std::cout << "failed to acquire lock" << std::endl;
    }
}

2.3 defer_lock

初始化这个mutex, 但是不去加锁;通过这个没加锁的mutex,可灵活调用其成员函数;

2.4 unique_lock成员函数

2.4.1 lock()

给互斥量加锁,若无法加锁,将会阻塞等待;

2.4.2 try_lock()

尝试给互斥量解锁,加锁失败返回false; 不阻塞;

2.4.3 unlock()

解锁互斥量,若解锁未上锁的互斥量将会抛出异常;

        terminate called after throwing an instance of 'std::system_error'
        what():  Operation not permitted

2.4.4 release()

返回锁管理的mutex指针,并释放所有权;也就是unique_lock和mutex将没有关系;程序员需要对返回的mutex进行管理;

2.4.5 owns_lock()

判断是否已经锁成功,锁成功返回true;

2.4.6 所有权移动

unique_lock的mutex的所有权是可移动的,但不能复制;

std::unique_lock<std::mutex> t_lock1(g_mutex);
//std::unique_lock<std::mutex> t_lock2(t_lock1); //不支持复制所有权
std::unique_lock<std::mutex> t_lock3(std::move(t_lock1));//所有权移动

3. lock_guard和unique_lock比较

特性std::lock_guardstd::unique_lock
手动解锁支持lock()/unlock()不支持
延迟锁定std::defer_lock不支持
尝试锁定try_to_lock不支持
性能开销略高(功能更多)更低(更轻量)
所有权转移std::move不支持

<think>好的,我现在需要回答用户关于Flowable工作流引擎与达梦数据库兼容性配置的问题。首先,用户提到了几个引用内容,我需要仔细查看这些引用,看看里面有没有相关的配置步骤或注意事项。 根据引用[1],里面提到了引入达梦数据库驱动包、配置数据源以及修改Flowable代码支持达梦数据库的具体步骤,比如修改ProcessEngineConfigurationImpl和DbSqlSessionFactory类。这部分应该是配置的核心内容,需要详细说明。 引用[3]则提到在结合SpringBatch时可能遇到的兼容性挑战,包括驱动检查、SQL调整、数据类型映射等。虽然用户主要问的是配置教程,但这些问题也可能在配置过程中出现,所以可以作为注意事项或优化建议加入回答中。 接下来,我需要按照用户的要求,结构清晰地分步骤讲解配置流程。首先可能需要说明如何引入达梦的JDBC驱动,比如在Maven项目中添加依赖,或者手动导入jar包。然后配置数据源,可能是在Spring Boot的application.yml里设置url、用户名、密码等信息,并指定数据库类型为达梦。 接下来是修改Flowable的代码部分。引用[1]提到需要修改ProcessEngineConfigurationImpl类,设置数据库类型和模式策略,可能还需要调整SQL会话工厂类,比如DbSqlSessionFactory,来支持达梦的特定语法。这部分可能需要用户手动覆盖默认配置,或者通过扩展类来实现。 另外,引用[3]中提到的SQL语句调整和数据类型映射也是需要注意的地方。达梦数据库可能有些SQL语法与Flowable默认的H2或MySQL不同,需要检查并修改Flowable生成的SQL,确保兼容。比如分页查询的语法,或者某些函数的替换。 事务管理和序列生成策略可能也需要调整,达梦可能使用不同的机制来生成主键,需要配置Flowable使用达梦的序列方式。此外,表结构和索引优化可能涉及到性能调整,比如根据达梦的建议调整索引类型或字段长度。 错误处理和日志记录也是配置后的重要步骤,确保在出现问题时能够及时定位,比如启用详细日志记录达梦的SQL执行情况。 最后,建议用户参考官方文档和社区资源,进行充分的测试,包括单元测试和集成测试,确保配置的正确性。引用[4]提到Liquibase支持人大金仓,可能类似的步骤可以借鉴,但达梦需要特定的处理。 在生成相关问题时,需要围绕配置步骤、常见问题、优化方法、与其他组件的集成以及国产化替代方案等方面展开。这样可以帮助用户更全面地了解整个兼容性配置的过程和可能遇到的问题。</think>### Flowable工作流引擎与达梦数据库兼容性配置教程 #### 一、兼容性基础 Flowable原生支持主流数据库(如MySQL、Oracle等),但通过调整配置和代码适配,可实现对达梦数据库的兼容[^3]。需重点关注驱动兼容性、SQL语法适配和数据类型映射。 #### 二、配置步骤 1. **驱动包引入** - Maven项目添加达梦驱动依赖(版本需与数据库匹配): ```xml <dependency> <groupId>dm.jdbc</groupId> <artifactId>dm-driver</artifactId> <version>8.1.1.193</version> </dependency> ``` - 非Maven项目需手动下载`DmJdbcDriver18.jar`并加入类路径[^1]。 2. **数据源配置** 在`application.yml`中配置达梦连接参数: ```yaml spring: datasource: url: jdbc:dm://localhost:5236/flowable_db username: admin password: dameng123 driver-class-name: dm.jdbc.driver.DmDriver ``` 3. **引擎配置修改** - 修改`ProcessEngineConfigurationImpl`类,指定数据库类型: ```java configuration.setDatabaseType("dm"); configuration.setDatabaseSchemaUpdate("true"); // 自动创建表 ``` - 覆盖`DbSqlSessionFactory`的SQL生成逻辑,适配达梦分页语法(如`LIMIT`改为`TOP`)[^1][^3]。 4. **SQL语法调整** - 修改Flowable的默认SQL模板文件(位于`org/flowable/db`),替换不兼容的函数(如`SYSDATE()`改为`SYSDATE`)。 #### 三、关键问题处理 1. **数据类型映射** | Flowable类型 | 达梦类型 | 处理方式 | |-------------|-------------|-------------------------| | VARCHAR(255)| VARCHAR(50) | 扩展字段长度或修改建表脚本 | | BLOB | CLOB | 调整字段类型并验证二进制数据存储 | 2. **事务管理** 在Spring配置中显式指定事务管理器: ```java @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } ``` 3. **序列生成策略** 修改流程实例ID生成方式,使用达梦序列: ```sql CREATE SEQUENCE FLW_SEQUENCE START WITH 1 INCREMENT BY 1; ``` #### 四、验证与测试 1. 执行`mvn test`运行单元测试,检查流程部署、任务处理等核心功能。 2. 使用`SELECT * FROM V$DM_INI`监控数据库性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天未及海宽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值