【Linux 編程】線程同步

來源:互聯網
上載者:User

  有關線程建立:【Linux 編程】線程編程

  當多個控制線程共用相同的資料時,需要確保每一個線程看到一致的資料。當一個線程修改資料變數時,其他線程在讀取這個變數值時就可能會看到不一致的資料。在變數修改時間多於一個儲存訪問的處理結構中,當儲存空間讀取或儲存空間寫這兩個周期交叉時,潛在的資料不一致性就會出現。為瞭解決這種資料不一致性的問題,線程利用鎖機制來保證在保證資料的一致性問題。若讀取資料或寫資料操作是原子操作,則不存在資料競爭或資料不一致性問題。

  1. 互斥鎖(pthread_mutex_t)

  互斥鎖保證同一時間只允許一個線程訪問資料。任何其他試圖擷取已加鎖的互斥鎖,就會被阻塞直到當前線程釋放該互斥鎖。若有多個線程被阻塞,在互斥鎖被釋放後,將喚醒所有阻塞線程,並採取先到先服務的策略來分配互斥鎖的使用權。

  互斥鎖的初始化

  • 使用常量PTHREAD_MUTEX_INITIALIZER來初始化靜態分配的互斥量;
  • 針對動態分配的互斥量,則調用函數pthread_mutex_init()進行初始化;調用函數pthread_mutex_destroy()來去初始化。需要注意,這兩個函數成對出現,使用方式類似於malloc/free。

  互斥鎖的使用

  • 函數pthread_mutex_lock()用來對互斥鎖加鎖。若互斥鎖已上鎖,則當前線程將被阻塞;
  • 若系統線程在不能擷取互斥鎖時被阻塞,則調用函數pthread_mutex_trylock()嘗試對互斥鎖進行加鎖。若成功擷取互斥鎖,則鎖住互斥鎖並返回0;若失敗,則返回非0,並設定錯誤碼為EBUSY。
  • 函數pthread_mutex_unlock()用來對互斥鎖進行解鎖。

  若線程試圖對同一個互斥鎖加鎖兩次,那麼它自身將會陷入死結狀態。在使用鎖機制時,需要預先設計加鎖的順序來避免死結的發生。

  例子:  

 1 #include <unistd.h> 2 #include <pthread.h> 3 #include <stdio.h> 4  5 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 6  7 void *start_routine(void *arg) 8 { 9     int res;10     int times = 0;11     pthread_t thread_id = pthread_self();12 13     while (1) {14         res = pthread_mutex_trylock(&lock);15         if (res != 0)16         {17             ++times;18             printf("Now the mutex lock is using!");19             printf("And thread ID 0x%x is trying %d times!\n",20                 (unsigned int) thread_id, times);21             sleep(2);22             continue;23         }24 25         printf("OK, 0x%x get mutex\n",     (unsigned int) thread_id);26         times = 0;27         sleep(10);28         pthread_mutex_unlock(&lock);29         30         if (times == 0)31             break;32     }33 34     pthread_exit((void *)thread_id);35 }36 37 int main()38 {39     pthread_t id0, id1;40     int res;41 42     res = pthread_create(&id0, NULL, start_routine, NULL);43     if (res < 0)44     {45         perror("pthread_create error!");46         return (-1);47     }48     49     res = pthread_create(&id1, NULL, start_routine, NULL);50     if (res < 0)51     {52         perror("thread_create error!");53         return (-1);54     }55 56     sleep(20);57     printf("MutexDemo is over!\n");58 59     return 0;60 61 }

View Code

  運行結果

  

  

  在多線程設計過程中不僅需要考慮加鎖的順序,還需要考慮鎖的粒度大小問題,即加鎖中處理資料的過程。若粒度太粗,就會發生出現很多線程阻塞等待相同的鎖,則導致並發性的效能改善微乎其微。如果鎖的粒度太小,那麼過多的鎖開銷會使系統效能受到影響,而且代碼會變得更加複雜。在設計加鎖時,需要在滿足鎖需求的情況下,在代碼複雜性和最佳化效能找到好的平衡點。

  2. 讀寫鎖(pthread_rwlock_t)

  不同於互斥鎖一次只能有一個線程可以對其加鎖。讀寫鎖具有三種狀態:讀模式下加鎖狀態、寫入模式下加鎖狀態、不加鎖狀態。一次只有一個線程可以佔有寫入模式的讀寫鎖,但多個線程可以同時佔有讀模式的讀寫鎖。因此,讀寫鎖也可以叫做共用-獨佔鎖。當讀寫鎖以讀模式鎖住時,它是以共用模式鎖住的;當它以寫入模式鎖住時,它是以獨佔模式鎖住的。

  若讀寫鎖以讀模式鎖住狀態時,如果有另外的線程試圖從寫入模式加鎖,將阻塞隨後的讀模式鎖請求。若多個線程共同以寫入模式加鎖,處理方式與互斥鎖處理方式相同。

  讀寫鎖的初始化使用pthread_rwlock_init()來完成,在釋放它們底層記憶體之前需要調用函數pthead_rwlock_destroy()來去初始化。

  讀寫鎖的使用

  • 讀模式加鎖,pthread_rwlock_rdlock()和pthread_rwlock_tryrdlock();
  • 寫入模式加鎖,pthread_rwlock_wrlock()和pthread_rwlock_trywrlock();
  • 解鎖操作,pthread_rwlock_unlock()。

  3.條件變數(pthread_cond_t)

  條件變數與互斥鎖一起使用的,允許線程以無競爭的方式等待特定的條件發生。線程在改變條件狀態之前首先鎖住互斥鎖,其他線程在擷取互斥鎖之前不會察覺到這種改變,因此必須鎖定互斥鎖以後才能計算條件。

  條件變數的初始化

  • 用常量PTHREAD_COND_INITIALIZER賦給靜態分配的條件變數;
  • 若條件變數是動態分配的,則利用pthread_cond_init()函數進行初始化;在釋放底層記憶體空間之前,必須使用pthread_cond_destroy()函數對條件變數去除初始化。

  條件變數使用函數pthread_cond_wait()等待條件為真。函數中的互斥鎖對條件進行保護,調用者把鎖住的互斥鎖傳給函數。函數把調用線程放在等待條件的線程列表中,然後對互斥鎖解鎖,這兩個操作是原子操作。函數在返回時,將再次獲得互斥鎖的控制權。函數pthread_cond_timedwait()在滿足pthread_cond_wait()函數的處理方式的基礎上,加上逾時處理。當在規定時間內條件不能滿足,則產生一個錯誤碼並返回。

  有兩個函數用於通知線程條件已滿足。pthread_cond_signal()函數將喚醒等待該條件的某個線程,而pthread_cond_broadcast()函數將喚醒等待該條件的所有線程。

  有關條件變數的編程例子:【Linux 編程】pthead_cond_t 的使用

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.