C++如何解决单例懒汉式和多线程问题

技术C++如何解决单例懒汉式和多线程问题这篇文章主要为大家展示了“C++如何解决单例懒汉式和多线程问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C++如何解决单例懒汉式和

本文主要给大家展示“C如何解决单懒多线程问题”,简单易懂,条理清晰,希望能帮你解决疑惑。让边肖带领大家学习学习《C如何解决单懒多线程问题》一文。

单一惰性和多线程问题

作为单例模式,在整个程序运行过程中,将只构建一个内存空间,以实现这一目标。

1.构造函数需要设置为私有成员。

2.需要一个私有静态指针来指向自身。

3.需要一个公共静态函数来公开上面的静态指针。

下面的代码是一个懒鬼的例子。

单击此处折叠或打开。

#包括牡蛎

使用命名空间标准;

类single_ins

{

私人:

int a;

int b;

single_ins()

{

a=0;

b=0;

}

静态single _ ins * myc

公众号:

void setval(const int a,const int b)

{

this-a=a;

this-b=b;

}

无效打印()

{

cout 'a: ' aendl

cout 'b: ' bendl

}

静态single_ins* setp()

{

//?

if(myc==NULL)

{

nbsp;          myc = new single_ins;

  •         }

  •         //?

  •         return myc;

  •     }

  •     static void  pfree()

  •     {

  •         if(myc != NULL)

  •         {

  •             delete myc;

  •             myc = NULL;

  •         }

  •     }

  • };

  • //? init static value

  • single_ins* single_ins::myc = NULL;

  • //nit static value

  • //single_ins* single_ins::myc = new single_ins;

  • int main()

  • {

  •     single_ins* a = single_ins::setp();

  •     single_ins* b = single_ins::setp();

  •     a->setval(10,20);

  •     b->print();

  •     cout<<a<<" "<<b<<endl;

  •     single_ins::pfree();

  • }

  • 但是上面的代码有明显的问题,就是遇到多线程的情况下,因为多个线程如果同事创建内存,由于彼此之间
    并不能及时检查到内存已经分配,会分配多个内存,这个时候我们至少需要一个线程间同步手段来让他们之间
    串行的执行,这个时候就涉及到两次检查(double check)
    如果没有mutex保护就是下面这个程序:

    点击(此处)折叠或打开

    1. #include <iostream>

    2. #include <unistd.h>

    3. using namespace std;

    4. //单列模式

    5. class single_ins

    6. {

    7.         private:

    8.                 int a;

    9.                 int b;

    10.                 single_ins()

    11.                 {

    12.                         cout<<"con begin\n";

    13.                         a= 0;

    14.                         b= 0;

    15.                         sleep(10); //故意拖长构造函数执行时间,造成懒汉式多线程问题

    16.                         cout<<"con end\n";

    17.                 }

    18.                 static single_ins* myc;//单例需要一个静态指针

    19.                 static int cnt;//构造调用次数统计

    20.         public:

    21.                 void setval(const int& a,const int& b)

    22.                 {

    23.                         this->a = a;

    24.                         this->b = b;

    25.                 }

    26.                 void print()

    27.                 {

    28.                         cout<<"a:"<<a<<endl;

    29.                         cout<<"b:"<<b<<endl;

    30.                         cout<<cnt<<endl;

    31.                 }

    32.                 static single_ins* setp() //函数获得指针值赋给静态成员指针变量

    33.                 {

    34.                         //懒汉式

    35.                         if(myc == NULL)

    36.                         {

    37.                                 myc = new single_ins;

    38.                                 cnt++;

    39.                         }

    40.                         //懒汉式

    41.                         return myc;

    42.                 }

    43.                 static void  pfree()

    44.                 {

    45.                         if(myc != NULL)

    46.                         {

    47.                                 delete myc;

    48.                                 myc = NULL;

    49.                         }

    50.                 }

    51. };

    52. //懒汉式 init static value

    53. single_ins* single_ins::myc = NULL;

    54. int single_ins::cnt = 0;

    55. //饿汉试 init static value

    56. //single_ins* single_ins::myc = new single_ins;

    57. /*

    58.    懒汉式的问题在于多线程调用的时候会出现问题,很可能同时建立出多个内存空间,

    59.    而不是单列了。

    60.    */

    61. void* main21(void* argc)

    62. {

    63.         single_ins* inp = (single_ins*)argc;

    64.         inp = single_ins::setp();

    65.         inp->setval(10,20);

    66.         inp->print();

    67.         cout<<inp<<"\n";

    68.         return NULL;

    69. }

    70. int main(void)

    71. {

    72.         pthread_t tid;

    73.         single_ins* a[3] = {NULL};

    74.         void* tret[3] = {NULL};

    75.         for(int i = 0 ; i<3; i++)

    76.         {

    77.                 pthread_create(&tid,NULL,main21,(void*)a[i]);

    78.                 //pthread_join(tid, &(tret[i]));

    79.         }

    80.         sleep(50);

    81.         single_ins::pfree();

    82. }

    会跑出结果
    con begin
    con begin
    con begin
    con end
    a:10
    b:20
    1
    0x7fc3880008c0
    con end
    a:10
    b:20
    2
    0x7fc3800008c0
    con end
    a:10
    b:20
    3
    0x7fc3840008c0

    可以看到
    0x7fc3880008c0 0x7fc3800008c0 0x7fc3840008c0
    明显是3个不同的内存空间 这就不对了,而且可以看到构造函数
    调用了3次
    为此我们使用mutex来保护临时

    如下:
     static single_ins* setp() //函数获得指针值赋给静态成员指针变量
     39         {
     40             //懒汉式
     41             if(myc == NULL)
     42             {
     43                 pthread_mutex_lock(&counter_mutex); //mutex 保护临界区
     44                 if(myc == NULL) //两次检查
     45                 {
     46                     myc = new single_ins;                                                                                                                           
     47                     cnt++;
     48                 }
     49                 pthread_mutex_unlock(&counter_mutex); //mutex结束
     50             }

    这样代码如下:

    点击(此处)折叠或打开

    1. #include <iostream>

    2. #include <unistd.h>

    3. using namespace std;

    4. pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;

    5. //单列模式

    6. class single_ins

    7. {

    8.         private:

    9.                 int a;

    10.                 int b;

    11.                 single_ins()

    12.                 {

    13.                         cout<<"con begin\n";

    14.                         a= 0;

    15.                         b= 0;

    16.                         sleep(10); //故意拖长构造函数执行时间,造成懒汉式多线程问题

    17.                         cout<<"con end\n";

    18.                 }

    19.                 static single_ins* myc;//单例需要一个静态指针

    20.                 static int cnt;//构造调用次数统计

    21.         public:

    22.                 void setval(const int& a,const int& b)

    23.                 {

    24.                         this->a = a;

    25.                         this->b = b;

    26.                 }

    27.                 void print()

    28.                 {

    29.                         cout<<"a:"<<a<<endl;

    30.                         cout<<"b:"<<b<<endl;

    31.                         cout<<cnt<<endl;

    32.                 }

    33.                 static single_ins* setp() //函数获得指针值赋给静态成员指针变量

    34.                 {

    35.                         //懒汉式

    36.                         if(myc == NULL)

    37.                         {

    38.                                 pthread_mutex_lock(&counter_mutex); //mutex 保护临界区

    39.                                 if(myc == NULL) //两次检查

    40.                                 {

    41.                                         myc = new single_ins;

    42.                                         cnt++;

    43.                                 }

    44.                                 pthread_mutex_unlock(&counter_mutex); //mutex结束

    45.                         }

    46.                         //懒汉式

    47.                         return myc;

    48.                 }

    49.                 static void  pfree()

    50.                 {

    51.                         if(myc != NULL)

    52.                         {

    53.                                 delete myc;

    54.                                 myc = NULL;

    55.                         }

    56.                 }

    57. };

    58. //懒汉式 init static value

    59. single_ins* single_ins::myc = NULL;

    60. int single_ins::cnt = 0;

    61. //饿汉试 init static value

    62. //single_ins* single_ins::myc = new single_ins;

    63. /*

    64.    懒汉式的问题在于多线程调用的时候会出现问题,很可能同时建立出多个内存空间,

    65.    而不是单列了。

    66.    */

    67. void* main21(void* argc)

    68. {

    69.         single_ins* inp = (single_ins*)argc;

    70.         inp = single_ins::setp();

    71.         inp->setval(10,20);

    72.         inp->print();

    73.         cout<<inp<<"\n";

    74.         return NULL;

    75. }

    76. int main(void)

    77. {

    78.         pthread_t tid;

    79.         single_ins* a[3] = {NULL};

    80.         void* tret[3] = {NULL};

    81.         for(int i = 0 ; i<3; i++)

    82.         {

    83.                 pthread_create(&tid,NULL,main21,(void*)a[i]);

    84.                 //pthread_join(tid, &(tret[i]));

    85.         }

    86.         sleep(50);

    87.         single_ins::pfree();

    88. }

    跑出的结果如下:

    con begin
    con end
    a:10a:10
    b:20
    1
    0x7f21f40008c0

    b:20
    1
    0x7f21f40008c0
    a:10
    b:20
    1
    0x7f21f40008c0

    现在就是正常的了。所以懒汉试单例遇到多线程一定要注意,饿汉试没有问题。
    当然这是一个小列子而已,线程安全是一个很大的话题,特别需要注意。

                   

    以上是“C++如何解决单例懒汉式和多线程问题”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

    内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/128604.html

    (0)

    相关推荐

    • linux 搭载yum私有仓库

      技术linux 搭载yum私有仓库 linux 搭载yum私有仓库yum私有仓库本地版
      @目录yum私有仓库本地版1.下载必须的软件包2.创建软件仓库3.下载对应的软件yum私有仓库本地版插图1)4.初

      礼包 2021年12月17日
    • 基础js动画

      技术基础js动画 基础js动画获取元素的样式
      getStyle函数
      此函数返回的是一个字符串,需要调用 parseInt() 或者 parseFloat() 将返回的结果转换为数字值。
      动画分类
      1.简

      礼包 2021年11月22日
    • k8s service实现原理(k8s调度工作原理)

      技术k8s的原理分析是怎样的这篇文章给大家介绍k8s的原理分析是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。k8s是一个开源的容器集群管理系统,可以实现容器集群的自动化部署、自动扩缩容、维护

      攻略 2021年12月15日
    • nodejs用哪些调试工具

      技术nodejs用哪些调试工具这篇文章将为大家详细讲解有关nodejs用哪些调试工具,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 调试node的工具:1、

      攻略 2021年11月7日
    • 线程池的创建方式有哪些

      技术线程池的创建方式有哪些这篇文章主要讲解了“线程池的创建方式有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“线程池的创建方式有哪些”吧!什么是线程池?线程池(Thr

      攻略 2021年10月21日
    • 以太坊公链的路线(以太坊如何销毁简单解释)

      技术以太坊如何将自定义数据写入到区块链中小编给大家分享一下以太坊如何将自定义数据写入到区块链中,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

      攻略 2021年12月25日