體驗mutex

liiinuuux發表於2014-03-19
10g新加了mutex,替換部分latch的功能。
經過了解,原來mutex不是oracle自己發明的,而是作業系統的一個功能。既然不是oracle獨家的,那我也想體驗一下,於是就有了下面小程式。

struct foo *fh[NHASH]是一個典型的hash table,上面有幾個表頭,每個表頭下面掛著一個foo連結串列,每個連結串列最後一個節點的next又指回表頭。
操作的過程就是   hold(f_count++) -> 操作 ->釋放(f_count--或free)

main函式里,對f2節點故意只hold,不釋放,最後列印的時候可以看到f_count是2

點選(此處)摺疊或開啟

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <pthread.h>
  4. #include <unistd.h>
  5. #include <string.h>

  6. #define NHASH 29
  7. #define HASH(fp) (((unsigned long)fp)%NHASH)

  8. struct foo *fh[NHASH];

  9. pthread_mutex_t hashlock = PTHREAD_MUTEX_INITIALIZER;

  10. struct foo
  11. {
  12.     int f_count;
  13.     pthread_mutex_t f_lock;
  14.     struct foo* f_next;
  15.     int f_id;
  16.     int f_value;
  17. };

  18. struct foo* foo_alloc(int id, int value)
  19. {
  20.     struct foo* fp = NULL;
  21.     struct foo* tmp = NULL;
  22.     int idx;
  23.     if((fp = malloc(sizeof(struct foo))) != NULL)
  24.     {
  25.         fp->f_count = 1;
  26.         if(pthread_mutex_init(&fp->f_lock, NULL) != 0)
  27.         {
  28.             free(fp);
  29.             return NULL;
  30.         }
  31.     }
  32.     
  33.     idx = HASH(fp);
  34.     pthread_mutex_lock(&hashlock);

  35.     if(fh[idx] == NULL)
  36.     {
  37.         fh[idx] = fp;
  38.     }
  39.     else
  40.     {
  41.         tmp = fh[idx];
  42.         while(tmp->f_next != NULL)
  43.         {
  44.             tmp = tmp->f_next;
  45.         }
  46.         tmp->f_next = fp;
  47.     }
  48.     fp->f_next = fh[idx];
  49.     pthread_mutex_lock(&fp->f_lock);
  50.     pthread_mutex_unlock(&hashlock);
  51.     fp->f_value = value;
  52.     fp->f_id = id;
  53.     pthread_mutex_unlock(&fp->f_lock);
  54.     return fp;
  55. }

  56. void foo_hold(struct foo* fp)
  57. {
  58.     pthread_mutex_lock(&fp->f_lock);
  59.     fp->f_count++;
  60.     pthread_mutex_unlock(&fp->f_lock);
  61. }

  62. struct foo* foo_find(int id)
  63. {
  64.     struct foo *fp;
  65.     int idx;
  66.     idx = HASH(fp);
  67.     pthread_mutex_lock(&hashlock);
  68.     for(fp=fh[idx]; fp!=NULL; fp=fp->f_next)
  69.     {
  70.         if(fp->f_id == id)
  71.         {
  72.             foo_hold(fp);
  73.             break;
  74.         }
  75.     }
  76.     pthread_mutex_unlock(&hashlock);
  77.     return(fp);
  78. }

  79. void foo_rele(struct foo* fp)
  80. {
  81.     struct foo* tfp;
  82.     int idx;
  83.     
  84.     pthread_mutex_lock(&fp->f_lock);
  85.     if(fp->f_count <= 1)
  86.     {
  87.         pthread_mutex_lock(&hashlock);
  88.         idx = HASH(fp);
  89.         tfp = fh[idx];
  90.         if (tfp == fp)
  91.         {
  92.             if(fp->f_next != fh[idx]) fh[idx] = fp->f_next;
  93.             else fh[idx] = NULL;
  94.         }
  95.         else
  96.         {
  97.             while(tfp->f_next != fp)
  98.             {
  99.                 tfp = tfp->f_next;
  100.             }
  101.             tfp->f_next = fp->f_next;
  102.         }
  103.         pthread_mutex_unlock(&hashlock);
  104.         pthread_mutex_unlock(&fp->f_lock);
  105.         pthread_mutex_destroy(&fp->f_lock);
  106.         free(fp);
  107.     }
  108.     else
  109.     {
  110.         fp->f_count--;
  111.         pthread_mutex_unlock(&fp->f_lock);
  112.     }
  113. }

  114. void main()
  115. {
  116.     struct foo* f1 = foo_alloc(1, 100);
  117.     struct foo* f2 = foo_alloc(2, 200);
  118.     
  119.     foo_hold(f1);
  120.     f1->f_value = 111;
  121.     foo_rele(f1);

  122.     foo_hold(f2);
  123.     f2->f_value = 222;

  124.     foo_rele(f1);

  125.     int i;
  126.     for(i=1; i<NHASH; i++)
  127.     {
  128.         if(fh[i] != NULL)
  129.         {
  130.             printf(\"fh[%d]: id=%d, value=%d, count=%d\\n\", i, fh[i]->f_id, fh[i]->f_value, fh[i]->f_count);
  131.         }
  132.     }

  133.     return;
  134. }

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26239116/viewspace-1124827/,如需轉載,請註明出處,否則將追究法律責任。

相關文章