乐观锁的实现与应用

乐观锁就是尽量让大家共享使用资源,当真的发生了资源的重要改变的时候,才给共享使用资源的所以线程一个通知,收到通知的线程回滚之前的行为。乐观锁通常在数据库使用,数据库大概比较适合回滚吧。

一般程序代码里面可能很难回滚,所以通常不适用。

但扩展一下概念,比如 new  一个指针变量,传递给多个线程。里面可能都会使用它,但只能有一个线程可以释放它,但不知道是哪个线程。当然,这里假设new 这个指针的地方 并不适合delete(多线程程序里,可能有时候有些地方会出现这种情况)。 那么每个使用指针的线程 其实都需要关注指针是否被释放了,如果被释放了还在使用的话 就会出现访问错误。 同样的, 准备删除这个指针的线程,是否可以马上删除它?不可以,所以删除前必须给一个通知,收到通知的线程都会停止访问该指针了。

  所以以上这种情况,所有线程都乐观访问了资源,直到收到通知才释放锁(释放锁即为放弃资源使用权),通知完成的线程最后清理锁。

实现代码如下:



class OptLock{

public:

    OptLock()
        :m_iCount(0){
    }
  // 加锁 ,计数加1
    unsigned int  Lock()
    {
        int old = m_iCount ;
    
        while(old == InterlockIncrease(&m_iCount))
        {
            old = m_iCount;
        }
        return m_iCount;
    }
  //解锁, 计数减1
    unsigned int  Unlock()
    {        
        unsigned int old = m_iCount ;
        if(old == 0)
            return  0;
    
        while(old == InterlockDecrease(&m_iCount))
        {
            old = m_iCount;
        }
        return m_iCount;
    
    }

    //高位设置 1 ,表示通知
    int  Notify()
    {
        unsigned int mask =  0x0001ffff;
        
        volatile unsigned int newcount = m_iCount&mask ;
        unsigned int old = m_iCount;

        while(::InterlockedCompareExchange(m_iCount,newcount,old) == old)
        {
            newcount = m_iCount&mask ;
            old = m_iCount;
        }

        return 0;
    }
  //判断该锁是否有重大变化 ,如果true,表示要尽快释放锁资源
    bool IsNotify() const
    {
        return (m_iCount>>16)
    }

    // 判断是否拥有该锁的线程是否都释放完成了
    bool IsAllRelease()
    {

        unsigned int mask =  0x0000ffff;

        if(IsNotify())
        {
            return (mask& m_iCount==0);
        }
    }
private:

    volatile unsigned int  m_iCount;
};

使用方法如下:

 OptLock  g_Lock; 


读取指针

UINT ThreadFunA(LPVOID pVoid)

{

         if(g_Lock.IsNotify()==false)

      {

           g_Lock.Lock();

          Int* p = (int*) pVoid;

               ......

            if(g_Lock.IsNotify())

               { //马上退出

           g_Lock.UnLock;

                  return 0; 

                 }


.....................

          g_Lock.UnLock();

 

      } 

return 0;

 }

// 删除线程

UINT ThreadFunB (LPVOID pvoid )

{           

           if(g_Lock.IsNotif()

          {

              g_Lock.Lock();

               int * p = (int*) pvoid ;

                 ......

              // 准备删除指针了

             g_Lock.Notify();

          while( IsAllRelease () == false) {};

            g_Lock.UnLock();

          delete p ;


         }

  }




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
乐观锁和悲观锁是在并发控制中常用的两种策略。乐观锁并未真正加锁,它通过记录数据版本来实现并发控制。在更新数据时,乐观锁会先读取数据的版本信息,然后再进行更新操作。如果在更新期间,其他事务已经修改了数据,那么当前事务的更新操作就会失败,需要重新尝试。乐观锁的优点是效率高,适合应用在读为主的场景下。 相反,悲观锁依赖数据库提供的锁机制,它在读取数据时会将数据进行加锁,确保其他事务不能修改数据。这种策略的缺点是效率相对较低,因为它会对系统的吞吐性能产生一定的影响。悲观锁适用于写为主的场景,因为它可以有效地保证数据的一致性。 因此,乐观锁和悲观锁的应用主要取决于业务场景和系统需求。如果并发读取较多,并且对数据一致性要求不高,可以选择乐观锁。而如果并发写入较多,并且对数据一致性要求较高,可以选择悲观锁。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [乐观锁和悲观锁全面总结及实际应用介绍](https://blog.csdn.net/dmlcq/article/details/127655568)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值