我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

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

单例懒汉式和多线程问题


作为单例模式,是在整个程序运行期间只会建立一份内存空间,为了达到这个目标
1、需要将构造函数设置为私有成员
2、需要一个私有的静态指针指向自身
3、需要一个公有的静态函数将这个上面的静态指针露出来

如下的代码就是一个懒汉式的单例

点击(此处)折叠或打开

  1. #include<iostream>

  2. using namespace std;

  3. class single_ins

  4. {

  5. private:

  6.     int a;

  7.     int b;

  8.     single_ins()

  9.     {

  10.         a= 0;

  11.         b= 0;

  12.     }

  13.     static single_ins* myc;

  14. public:

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

  16.     {

  17.         this->a = a;

  18.         this->b = b;

  19.     }

  20.     void print()

  21.     {

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

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

  24.     }

  25.     static single_ins* setp()

  26.     {

  27.         //?

  28.         if(myc == NULL)

  29.         {

  30.             myc = new single_ins;

  31.         }

  32.         //?

  33.         return myc;

  34.     }

  35.     static void  pfree()

  36.     {

  37.         if(myc != NULL)

  38.         {

  39.             delete myc;

  40.             myc = NULL;

  41.         }

  42.     }

  43. };

  44. //? init static value

  45. single_ins* single_ins::myc = NULL;

  46. //nit static value

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

  48. int main()

  49. {

  50.     single_ins* a = single_ins::setp();

  51.     single_ins* b = single_ins::setp();

  52.     a->setval(10,20);

  53.     b->print();

  54.     cout<<a<<" "<<b<<endl;

  55.     single_ins::pfree();

  56. }

但是上面的代码有明显的问题,就是遇到多线程的情况下,因为多个线程如果同事创建内存,由于彼此之间
并不能及时检查到内存已经分配,会分配多个内存,这个时候我们至少需要一个线程间同步手段来让他们之间
串行的执行,这个时候就涉及到两次检查(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. void* main21(void* argc)

  58. {

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

  60.         inp = single_ins::setp();

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

  62.         inp->print();

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

  64.         return NULL;

  65. }

  66. int main(void)

  67. {

  68.         pthread_t tid;

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

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

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

  72.         {

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

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

  75.         }

  76.         sleep(50);

  77.         single_ins::pfree();

  78. }

会跑出结果
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. void* main21(void* argc)

  64. {

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

  66.         inp = single_ins::setp();

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

  68.         inp->print();

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

  70.         return NULL;

  71. }

  72. int main(void)

  73. {

  74.         pthread_t tid;

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

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

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

  78.         {

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

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

  81.         }

  82.         sleep(50);

  83.         single_ins::pfree();

  84. }

跑出的结果如下:

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


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


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

               

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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

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

java单例模式和线程安全问题怎么解决

这篇文章主要介绍“java单例模式和线程安全问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“java单例模式和线程安全问题怎么解决”文章能帮助大家解决问题。单例模式、多实例模式、和线程安全
2023-07-05

C++多线程编程之如何解决多线程数据共享问题

这篇文章主要讲解了“C++多线程编程之如何解决多线程数据共享问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++多线程编程之如何解决多线程数据共享问题”吧!通过容器创建多个线程#incl
2023-06-15

redis单线程并发问题如何解决

Redis是一个单线程的内存数据库,它使用了事件驱动的模型,通过将请求放入一个队列中顺序执行来实现并发处理。但是,在高并发情况下,可能会出现性能瓶颈。要解决Redis的单线程并发问题,可以考虑以下几个方面:1. 水平扩展:通过使用Redis
2023-09-11

java多线程并发问题如何解决

在Java中,可以使用以下方法来解决多线程并发问题:1. 使用synchronized关键字:可以通过在方法或代码块前加上synchronized关键字来实现同步,确保同一时间只有一个线程可以访问被同步的代码块或方法。2. 使用Lock接口
2023-09-27

如何解决 C++ 多线程编程中常见的死锁问题?

如何解决 c++++ 多线程编程中的常见死锁问题?避免死锁的技术:加锁顺序:始终以相同的顺序获取锁。死锁检测:使用算法检测并解决死锁。超时:为锁设置超时值,防止线程无限期等待。优先级反转:分配不同的优先级,减少死锁可能性。如何解决 C++
如何解决 C++ 多线程编程中常见的死锁问题?
2024-05-13

Java单例模式中的线程安全问题怎么解决

今天小编给大家分享一下Java单例模式中的线程安全问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一. 使用多线程
2023-07-02

C++中的多线程同步问题和解决方法概述

C++中的多线程同步问题和解决方法概述多线程编程是一种并发编程的方式,有助于提高程序的性能和效率。然而,多线程编程也带来了一系列的挑战和问题,其中最突出的是多线程同步问题。本文将概述C++中的多线程同步问题,并介绍几种常见的解决方法。同时,
2023-10-22

java全局变量多线程问题如何解决

在Java中,可以使用以下几种方式来解决全局变量多线程问题:1. 使用synchronized关键字:在访问全局变量时,使用synchronized关键字来确保同一时间只有一个线程可以访问该变量。这样可以防止多个线程同时修改全局变量,从而避
2023-08-26

如何解决PHP无法实现多线程的问题

这篇文章主要为大家展示了“如何解决PHP无法实现多线程的问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何解决PHP无法实现多线程的问题”这篇文章吧。其实的是大多数情况下,你大可不必使用fo
2023-06-17

C#开发中如何处理并发编程和多线程同步问题及解决方法

C#开发中如何处理并发编程和多线程同步问题及解决方法在如今的软件开发领域中,并发编程已经成为一种常见的需求。在许多应用程序中,我们需要同时处理多个任务,而多线程是实现这个目标的一种常见方式。然而,处理并发编程和多线程同步问题并不容易。本文将
2023-10-22

C#开发中如何处理多线程同步和互斥问题

C#开发中如何处理多线程同步和互斥问题,需要具体代码示例概述:在C#中,多线程的使用成为了常见的开发需求。然而,由于多线程同时操作共享资源可能导致数据不一致或者冲突的问题,因此需要使用同步和互斥机制来解决这些问题。本文将介绍在C#开发中如何
2023-10-22

详解如何使用C++写一个线程安全的单例模式

这篇文章主要为大家详细介绍了如何使用C++写一个线程安全的单例模式,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
2022-11-13

C#开发中如何处理线程同步和并发访问问题及解决方法

C#开发中如何处理线程同步和并发访问问题及解决方法随着计算机系统和处理器的发展,多核处理器的普及使得并行计算和多线程编程变得非常重要。在C#开发中,线程同步和并发访问问题是我们经常面临的挑战。没有正确处理这些问题,可能会导致数据竞争(Dat
2023-10-22

C++并发编程:如何识别和解决死锁问题?

在 c++++ 并发编程中,死锁问题发生在一或多个线程无限期等待其他线程释放资源时,导致程序挂起。我们可以使用 std::lock_guard 和 std::unique_lock 实现死锁检测,如果发生死锁,会抛出 std::system
C++并发编程:如何识别和解决死锁问题?
2024-05-04

Java多线程高并发中如何解决ArrayList与HashSet和HashMap不安全的问题

这篇文章主要为大家展示了“Java多线程高并发中如何解决ArrayList与HashSet和HashMap不安全的问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java多线程高并发中如何解决
2023-06-25

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录