溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

C++如何解決單例懶漢式和多線(xiàn)程問(wèn)題

發(fā)布時(shí)間:2021-12-01 09:11:57 來(lái)源:億速云 閱讀:120 作者:小新 欄目:大數(shù)據(jù)

這篇文章主要為大家展示了“C++如何解決單例懶漢式和多線(xiàn)程問(wèn)題”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“C++如何解決單例懶漢式和多線(xiàn)程問(wèn)題”這篇文章吧。

單例懶漢式和多線(xiàn)程問(wèn)題


作為單例模式,是在整個(gè)程序運(yùn)行期間只會(huì)建立一份內(nèi)存空間,為了達(dá)到這個(gè)目標(biāo)
1、需要將構(gòu)造函數(shù)設(shè)置為私有成員
2、需要一個(gè)私有的靜態(tài)指針指向自身
3、需要一個(gè)公有的靜態(tài)函數(shù)將這個(gè)上面的靜態(tài)指針露出來(lái)

如下的代碼就是一個(gè)懶漢式的單例

點(diǎn)擊(此處)折疊或打開(kāi)

  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. }

但是上面的代碼有明顯的問(wèn)題,就是遇到多線(xiàn)程的情況下,因?yàn)槎鄠€(gè)線(xiàn)程如果同事創(chuàng)建內(nèi)存,由于彼此之間
并不能及時(shí)檢查到內(nèi)存已經(jīng)分配,會(huì)分配多個(gè)內(nèi)存,這個(gè)時(shí)候我們至少需要一個(gè)線(xiàn)程間同步手段來(lái)讓他們之間
串行的執(zhí)行,這個(gè)時(shí)候就涉及到兩次檢查(double check)
如果沒(méi)有mutex保護(hù)就是下面這個(gè)程序:

點(diǎn)擊(此處)折疊或打開(kāi)

  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); //故意拖長(zhǎng)構(gòu)造函數(shù)執(zhí)行時(shí)間,造成懶漢式多線(xiàn)程問(wèn)題

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

  17.                 }

  18.                 static single_ins* myc;//單例需要一個(gè)靜態(tài)指針

  19.                 static int cnt;//構(gòu)造調(diào)用次數(shù)統(tǒng)計(jì)

  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() //函數(shù)獲得指針值賦給靜態(tài)成員指針變量

  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.    懶漢式的問(wèn)題在于多線(xiàn)程調(diào)用的時(shí)候會(huì)出現(xiàn)問(wèn)題,很可能同時(shí)建立出多個(gè)內(nèi)存空間,

  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. }

會(huì)跑出結(jié)果
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個(gè)不同的內(nèi)存空間 這就不對(duì)了,而且可以看到構(gòu)造函數(shù)
調(diào)用了3次
為此我們使用mutex來(lái)保護(hù)臨時(shí)

如下:
 static single_ins* setp() //函數(shù)獲得指針值賦給靜態(tài)成員指針變量
 39         {
 40             //懶漢式
 41             if(myc == NULL)
 42             {
 43                 pthread_mutex_lock(&counter_mutex); //mutex 保護(hù)臨界區(qū)
 44                 if(myc == NULL) //兩次檢查
 45                 {
 46                     myc = new single_ins;                                                                                                                           
 47                     cnt++;
 48                 }
 49                 pthread_mutex_unlock(&counter_mutex); //mutex結(jié)束
 50             }


這樣代碼如下:

點(diǎn)擊(此處)折疊或打開(kāi)

  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); //故意拖長(zhǎng)構(gòu)造函數(shù)執(zhí)行時(shí)間,造成懶漢式多線(xiàn)程問(wèn)題

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

  18.                 }

  19.                 static single_ins* myc;//單例需要一個(gè)靜態(tài)指針

  20.                 static int cnt;//構(gòu)造調(diào)用次數(shù)統(tǒng)計(jì)

  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() //函數(shù)獲得指針值賦給靜態(tài)成員指針變量

  34.                 {

  35.                         //懶漢式

  36.                         if(myc == NULL)

  37.                         {

  38.                                 pthread_mutex_lock(&counter_mutex); //mutex 保護(hù)臨界區(qū)

  39.                                 if(myc == NULL) //兩次檢查

  40.                                 {

  41.                                         myc = new single_ins;

  42.                                         cnt++;

  43.                                 }

  44.                                 pthread_mutex_unlock(&counter_mutex); //mutex結(jié)束

  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.    懶漢式的問(wèn)題在于多線(xiàn)程調(diào)用的時(shí)候會(huì)出現(xiàn)問(wèn)題,很可能同時(shí)建立出多個(gè)內(nèi)存空間,

  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. }

跑出的結(jié)果如下:

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


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


現(xiàn)在就是正常的了。所以懶漢試單例遇到多線(xiàn)程一定要注意,餓漢試沒(méi)有問(wèn)題。
當(dāng)然這是一個(gè)小列子而已,線(xiàn)程安全是一個(gè)很大的話(huà)題,特別需要注意。

               

以上是“C++如何解決單例懶漢式和多線(xiàn)程問(wèn)題”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI