詳解線程的信號量和互斥鎖

来源:https://www.cnblogs.com/liudw-0215/archive/2018/04/28/8966645.html
-Advertisement-
Play Games

前言:有個問題感覺一直會被問道:進程和線程的區別?也許之前我會回答: 進程:資源分配最小單位 線程:輕量級的進程 是系統調度的最小單位 由進程創建 多個線程共用進程的資源 但是現在我覺得一個比喻回答的更好:程式就像靜止的火車,進程是運行的火車,線程是運行火車的每節車廂。 個人感覺理解遠比背些概念性東 ...


  前言:有個問題感覺一直會被問道:進程和線程的區別?也許之前我會回答:

  • 進程:資源分配最小單位
  • 線程:輕量級的進程 是系統調度的最小單位 由進程創建 多個線程共用進程的資源

  但是現在我覺得一個比喻回答的更好:程式就像靜止的火車,進程是運行的火車,線程是運行火車的每節車廂。

個人感覺理解遠比背些概念性東西更好。

  一、線程

  通常在一個進程中可以包含若幹個線程,當然一個進程中至少有一個線程,不然沒有存在的意義。線程可以利用進程所擁有的資源,在引入線程的操作系統中,通常都是把進程作為分配資源的基本單位,而把線程作為獨立運行和獨立調度的基本單位,由於線程比進程更小,基本上不擁有系統資源,故對它的調度所付出的開銷就會小得多,能更高效的提高系統多個程式間併發執行的程度。

  1、線程相關函數 

  • pthread_create函數

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);

註:Compile and link with -pthread.//編譯時 要加-lpthread
功能:創建線程
參數1:線程的ID
參數2:NULL
參數3:線程處理函數
參數4: 傳遞給線程處理函數的參數
成功放回0 失敗返回-1

  • pthread_join函數

#include <pthread.h>

int pthread_join(pthread_t thread, void **retval);

功能:以阻塞的方式等待指定線程 主線程如果執行到此函數 將阻塞等待子線程結束

  程式1-1演示兩個函數用法:

#include"my.h"

void *func(void *p) 
{
    *(int*)p = 10; 
    printf("%d\n",*(int *)p);
}

int main()
{
    int x=100;
    pthread_t id; 
    int ret = pthread_create(&id,NULL,func,&x);
    if(ret<0)
    {   
        perror("pthread_create");
        exit(-1);
    }   
    pthread_join(id,NULL);
    return 0;

}

註:頭文件“my.h”為自定義文件,詳情請參考這篇博客:http://www.cnblogs.com/liudw-0215/p/8946879.html  

運行演示如下圖:

  二、信號量

  信號量(Semaphore),有時被稱為信號燈,是在多線程環境下使用的一種設施, 它負責協調各個線程, 以保證它們能夠正確、合理的使用公共資源。

  1、信號量相關函數

  • sem_init函數

sem_t s;

#include <semaphore.h>

int sem_init(sem_t *sem, int pshared, unsigned int value);

格式:sem_init(&s,0,n)
功能:初始化一個信號量的值為value
參數2:是否在進程間使用 一般總是0 表示不在進程間使用
參數3:計數器的初始值

  • sem_wait函數

int sem_wait(sem_t *sem);
把計數器減一 它會等待 直到信號量有個非零值才會執行減法操作
如果對值為0的信號量用sem_wait 這個函數會等待 直到其他線程增加該信號量的值 使其不再是0為止
如果對值為2的信號量調用sem_wait 線程會繼續執行 但信號量的值會減一。
如果兩個線程同時在sem_wait調用上等待同一個信號量變為非0值 那麼當信號量 被第三個線程+1 只有一個等待線程開始對信號量-1
然後繼續執行 另一個線程還繼續等待。

  • sem_post函數

#include <semaphore.h>

int sem_post(sem_t *sem);

功能:把 計數器+1

  程式2-1介紹信號量使用

#include"my.h"

sem_t s;

void *fun(void *p)
{
    int i;
    int *pa = (int *)p;
    for(i=0;i<4;i++)
    {
        sem_wait(&s);//將計數器的值-1 
        pa[i] +=i;
    }
    for(i=0;i<4;i++)
    {
        printf("%-02d",pa[i]);
    }
    printf("\n");
    return  NULL;
}

void *fun1(void *p)
{
    sem_wait(&s);//將計數器的值-1 
    puts("fun1 run!");
    return NULL;
}

int main()
{
    int i=0,ret=0;
    int a[5]={0};
    sem_init(&s,0,0);//設置信號量的值為0
    pthread_t tid[2];
    ret = pthread_create(&tid[0],NULL,fun,a);
    if(ret<0)
    {
        perror("pthread_create");
        exit(-1);
    }
    ret = pthread_create(&tid[1],NULL,fun1,a);
    if(ret<0)
    {
        perror("pthread_create");
        exit(-1);
    }

    for(i=0;i<5;i++)
    {
        sem_post(&s);//將計數器的值+1  
    }

    pthread_join(tid[0],NULL);
    pthread_join(tid[1],NULL);
    return 0;
}

運行演示如下圖:

  三、互斥鎖

  互斥鎖: 只要被鎖住,其他任何線程都不可以訪問被保護的資源

  1、互斥鎖相關函數

pthread_mutex_t m;

pthread_mutex_init(&m,NULL) //初始化互斥量
pthread_mutex_lock(&m);//對一個互斥量加鎖 如果互斥量已經加鎖 函數會一直等待 等到有線程把這個互斥量解鎖後 再去加鎖
pthread_mutex_unlock(&m);//對一個互斥量解鎖 哪個線程加鎖只能由這個線程解鎖 別的線程不能 解鎖

  程式3-1演示互斥鎖應用:

#include"my.h"

pthread_mutex_t m;

void* thread_fun(void  *p)
{
    int i;
    pthread_mutex_lock(&m);//加鎖
    for(i=0;i<3;i++)
    {
        printf("PID:%d tid:%lu\n",getpid(),pthread_self());
        sleep(1);
    }
    pthread_mutex_unlock(&m);//解鎖
    pthread_exit(NULL);
}

int main()
{
    pthread_mutex_init(&m,NULL);//初始化鎖
    int i,ret;
    pthread_t tid[3];
    for(i=0;i<3;i++)
    {
        ret = pthread_create(&tid[i],NULL,thread_fun,NULL);
        if(ret<0)
        {
            printf("pthread_create  %d error\n",i);
            exit(-1);
        }
    }
    
    
    
    for(i=0;i<3;i++)
    {
        pthread_join(tid[i],NULL);
    }
    return 0;
}

  運行演示如下圖:

總結:主要介紹線程同步的信號量和互斥鎖,以後有時間將更加詳細介紹其中實現原理。

  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天在安裝 vim 的時候出現了 Package 'vim' has no installation candidate的問題 解決方法如下:# apt-get update# apt-get upgrade# apt-get install <packagename> 這樣就可以正常使用 apt- ...
  • 前言:前面有篇博客已經介紹了線程、線程的信號量和互斥鎖,請參考博客:http://www.cnblogs.com/liudw-0215/p/8966645.html,接下來將介紹線程池。 一、理解 線程池能有效的處理多個線程的併發問題,避免大量的線程因為互相強占系統資源導致阻塞現象,能夠有效的降低頻 ...
  • CentOS6關閉防火牆使用以下命令: CentOS7關閉防火牆使用以下命令: 若安裝了iptables-service,也可以使用下麵的命令: ...
  • [TOC] 靜態庫 先說說我們為什麼需要庫? 當有些代碼我們大量會在程式中使用比如(scanf,printf等)這些函數我們需要在程式中頻繁使用,於是我們就把這些代碼編譯為庫文件,在需要使用時我們直接鏈接即可。 定義: & 8195;程式在 時把靜態庫的代碼鏈接到可執行程式中,在代碼運行時不再需要靜 ...
  • 簡介 vim是Linux 系統下類似於Windows的記事本的編輯器。 vim 中經常使用的三種模式 一般模式:瀏覽文件內容。 插入模式:編輯文件內容。 底行模式:進行保存編輯內容,退出等操作。 基本命令操作 vim filename ,打開文件,進入一般模式。 那麼現在如果我想修改文件怎麼辦呢? ...
  • 一開始,坐著上機實驗,一直搞不通為什麼虛擬機上的客戶機可以ping通自己的ip也可以ping通自己本身的ip,但是主機ping不通虛擬機的客戶機,也ping不通虛擬機的網關。 嘗試了各種問題,也追出了一大串問題: 1.宿主上,乙太網屬性什麼都沒有,連接時使用的框+此連接使用下列項目(o)裡面都沒有內 ...
  • 在安裝配置完zabbix_agentd以後,網頁端出現 Get value error: cannot connect to [[192.168.238.139]:10050]: [113] No route to host 錯誤,客戶端主機無法被監聽 解決方法: 首先在服務端ping一下客戶端的I ...
  • 線上箭頭表示畫線的方向。WINDING模式和ALTERNATE模式都會填充三個封閉的L型區域,號碼從1到3。兩個更小的內部區域,號碼為4和5,在ALTERNATE模式下不被填充。但是在WINDING模式下,號碼5的區域會被填充,這是因為區域的內部到達圖形的外部必須穿過兩條相同方向的線。號碼為4的區域 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...