在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

多線程編程基礎知識總結!

冬至子 ? 來源:嵌入式大雜燴 ? 作者:LinuxZn ? 2023-06-07 14:22 ? 次閱讀

什么是多線程編程

1、線程和進程的區別

進程是指正在運行的程序,它擁有獨立的內存空間和系統資源,不同進程之間的數據不共享。

線程是進程內的執行單元,它與同一進程內的其他線程共享進程的內存空間和系統資源。

2、多線程的優勢和應用場景

多線程是一種并發編程方式,它的優勢包括:

  • 提高程序的響應速度和運行效率(多核CPU下的多線程)
  • 充分利用CPU資源,提高系統的利用率
  • 支持多個任務并行執行,提高程序的可擴展性和可維護性

Linux下的多線程編程

Linux下C語言多線程編程依賴于pthread多線程庫。pthread庫是Linux的多線程庫,是POSIX標準線程API的實現,它提供了一種創建和操縱線程的方法,以及一些同步機制,如互斥鎖、條件變量等。

頭文件:

`#include < pthread.h >  
`

編譯鏈接需要鏈接鏈接庫 pthread。

一、線程的基本操作

1、pthread_create

/**
 * @brief 創建一個線程
 *
 * Detailed function description
 *
 * @param[in] thread: 一個指向線程標識符的指針,線程調用后,該值被設置為線程ID;pthread_t為unsigned long int
 * @param[in] attr: 用來設置線程屬性
 * @param[in] start_routine: 線程函數體,線程創建成功后,thread 指向的內存單元從該地址開始運行
 * @param[in] arg: 傳遞給線程函數體的參數
 *
 * @return 線程創建成功,則返回0,失敗則返回錯誤碼,并且 thread 內容是未定義的
 */
int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*(*start_routine)(void*), void* arg);

例子test.c:創建一個線程,每1s打印一次。

`#include < stdio.h >  
#include < stdlib.h >  
#include < unistd.h >  
#include < pthread.h >  
  
static pthread_t s_thread_id;  
static unsigned char s_thread_running = 0;  
  
void *thread_fun(void *arg)  
{  
    s_thread_running = 1;  
    while (s_thread_running)  
    {  
        printf("thread run...\\n");  
        sleep(1);  
    }  
  
    pthread_exit(NULL);  
}  
  
int main(void)  
{  
    int ret = 0;  
  
    printf("Before Thread\\n");  
    ret = pthread_create(&s_thread_id, NULL, thread_fun, NULL);  
    if (ret != 0)  
    {  
        printf("thread_create error!\\n");  
        exit(EXIT_FAILURE);  
    }  
  
    ret = pthread_join(s_thread_id, NULL); ///< 阻塞等待線程結束  
    if (ret != 0)  
    {  
        printf("pthread_join error!\\n");  
        exit(EXIT_FAILURE);  
    }  
    printf("After Thread\\n");  
    exit(EXIT_SUCCESS);  
}  
`

編譯、運行:

`gcc test.c -o test -lpthread  
`

image.png

2、pthread_join

`/**  
 * @brief 等待某個線程結束  
 *  
 * Detailed function description: 這是一個線程阻塞函數,調用該函數則等到線程結束才繼續運行  
 *  
 * @param[in] thread: 某個線程的ID  
 * @param[in] retval: 用于獲取線程 start_routine 的返回值  
 *  
 * @return 線程創建成功,則返回0,失敗則返回錯誤碼,并且 thread 內容是未定義的  
 */  
int pthread_join(pthread_t thread, void **retval);  
`

例子test.c:創建一個線程,進行一次加法運算就返回。

`#include < stdio.h >  
#include < stdlib.h >  
#include < unistd.h >  
#include < pthread.h >  
  
static pthread_t s_thread_id;  
static unsigned char s_thread_running = 0;  
  
void *thread_fun(void *arg)  
{  
    static int res = 0;  
    int a = 1, b = 2;  
  
    res = a + b;  
    sleep(1);  
    printf("thread run, a + b = %d, addr = %p\\n", res, &res);  
  
    pthread_exit(&res);  
}  
  
int main(void)  
{  
    int ret = 0;  
    int *retval = NULL;  
  
    printf("Before Thread\\n");  
    ret = pthread_create(&s_thread_id, NULL, thread_fun, NULL);  
    if (ret != 0)  
    {  
        printf("pthread_create error!\\n");  
        exit(EXIT_FAILURE);  
    }  
  
    ret = pthread_join(s_thread_id, (void **)&retval); ///< 阻塞等待線程結束  
    if (ret != 0)  
    {  
        printf("pthread_join error!\\n");  
        exit(EXIT_FAILURE);  
    }  
    if (retval != NULL)  
    {  
        printf("After Thread, retval = %d, addr = %p\\n", (int)*retval, retval);  
    }  
  
    exit(EXIT_SUCCESS);  
}  
`

編譯、運行:

image.png

3、pthread_exit

`/**  
 * @brief 退出線程  
 *  
 * Detailed function description  
 *  
 * @param[in] retval: 它指向的數據將作為線程退出時的返回值  
 *  
 * @return void  
 */  
void pthread_exit(void *retval);  
`
  1. 線程將指定函數體中的代碼執行完后自行結束;
  2. 線程執行過程中,被同一進程中的其它線程(包括主線程)強制終止;
  3. 線程執行過程中,遇到 pthread_exit() 函數結束執行。

例子test.c:創建一個線程,每個1s打印一次,打印超過5次時調用pthread_exit退出。

#include < stdio.h >  
#include < stdlib.h >  
#include < unistd.h >  
#include < pthread.h >  
  
static pthread_t s_thread_id;  
static unsigned char s_thread_running = 0;  
const static char *thread_exit_str = "thread_exit ok!";  
  
void *thread_fun(void *arg)  
{  
    static int cnt = 0;  
      
    s_thread_running = 1;  
    while (s_thread_running)  
    {  
        cnt++;  
        if (cnt > 5)  
        {  
            pthread_exit((void*)thread_exit_str);  
        }  
        printf("thread run...\\n");  
        sleep(1);  
    }  
  
    pthread_exit(NULL);  
}  
  
int main(void)  
{  
    int ret = 0;  
    void *thread_res = NULL;  
  
    printf("Before Thread\\n");  
    ret = pthread_create(&s_thread_id, NULL, thread_fun, NULL);  
    if (ret != 0)  
    {  
        printf("thread_create error!\\n");  
        exit(EXIT_FAILURE);  
    }  
  
    ret = pthread_join(s_thread_id, (void**)&thread_res);  
    if (ret != 0)  
    {  
        printf("thread_join error!\\n");  
        exit(EXIT_FAILURE);  
    }  
    printf("After Thread, thread_res = %s\\n", (char*)thread_res);  
    exit(EXIT_SUCCESS);  
}

編譯、運行:

image.png

使用return退出線程與使用pthread_exit退出線程的區別?

return為通用的函數退出操作,pthread_exit專用與線程,既然pthread庫有提供專門的函數,自然用pthread_exit會好些,雖然使用return也可以。

看看return退出線程與使用pthread_exit退出線程的具體區別:退出主線程。使用pthread_exit退出主線程只會終止當前線程,不會影響進程中其它線程的執行;使用return退出主線程,主線程退出執行很快,所有線程都會退出。

例子:使用pthread_exit退出主線程

`#include < stdio.h >  
#include < stdlib.h >  
#include < unistd.h >  
#include < pthread.h >  
  
static pthread_t s_thread_id;  
static unsigned char s_thread_running = 0;  
const static char *thread_exit_str = "thread_exit ok!";  
  
void *thread_fun(void *arg)  
{  
    sleep(1);  
    printf("thread_fun run...\\n");  
    pthread_exit(NULL);  
}  
  
int main(void)  
{  
    int ret = 0;  
    void *thread_res = NULL;  
  
    printf("Before Thread\\n");  
    ret = pthread_create(&s_thread_id, NULL, thread_fun, NULL);  
    if (ret != 0)  
    {  
        printf("thread_create error!\\n");  
        exit(EXIT_FAILURE);  
    }  
      
    printf("main thread exit\\n");  
    pthread_exit(NULL);  
}  
`

編譯、運行:

image.png

例子:使用return退出主線程

`#include < stdio.h >  
#include < stdlib.h >  
#include < unistd.h >  
#include < pthread.h >  
  
static pthread_t s_thread_id;  
static unsigned char s_thread_running = 0;  
const static char *thread_exit_str = "thread_exit ok!";  
  
void *thread_fun(void *arg)  
{  
    sleep(1);  
    printf("thread_fun run...\\n");  
    pthread_exit(NULL);  
}  
  
int main(void)  
{  
    int ret = 0;  
    void *thread_res = NULL;  
  
    printf("Before Thread\\n");  
    ret = pthread_create(&s_thread_id, NULL, thread_fun, NULL);  
    if (ret != 0)  
    {  
        printf("thread_create error!\\n");  
        exit(EXIT_FAILURE);  
    }  
      
    printf("main thread exit\\n");  
      
    return 0;  
}  
`

編譯、運行:

image.png

4、pthread_self

`/**  
 * @brief 用來獲取當前線程ID  
 *  
 * Detailed function description  
 *  
 * @param[in] void  
 *  
 * @return 返回線程id  
 */  
pthread_t pthread_self(void);  
`

例子:

#include < stdio.h >  
#include < stdlib.h >  
#include < unistd.h >  
#include < pthread.h >  
  
static pthread_t s_thread_id;  
static unsigned char s_thread_running = 0;  
const static char *thread_exit_str = "thread_exit ok!";  
  
void *thread_fun(void *arg)  
{  
    static int cnt = 0;  
      
    s_thread_running = 1;  
    while (s_thread_running)  
    {  
        cnt++;  
        if (cnt > 5)  
        {  
            pthread_exit((void*)thread_exit_str);  
        }  
        printf("thread run(tid = %ld)...\\n", pthread_self());  
        sleep(1);  
    }  
  
    pthread_exit(NULL);  
}  
  
int main(void)  
{  
    int ret = 0;  
    void *thread_res = NULL;  
  
    pid_t pid = getpid();  
    printf("pid = %d\\n", pid);  
  
    printf("Before Thread\\n");  
    ret = pthread_create(&s_thread_id, NULL, thread_fun, NULL);  
    if (ret != 0)  
    {  
        printf("thread_create error!\\n");  
        exit(EXIT_FAILURE);  
    }  
  
    ret = pthread_join(s_thread_id, (void**)&thread_res);  
    if (ret != 0)  
    {  
        printf("thread_join error!\\n");  
        exit(EXIT_FAILURE);  
    }  
    printf("After Thread, thread_res = %s\\n", (char*)thread_res);  
    exit(EXIT_SUCCESS);  
}

編譯、運行:

image.png

5、pthraad_detach

/**  
 * @brief 分離線程  
 *  
 * Detailed function description: 分離線程,線程結束是系統自動回收線程的資源  
 *  
 * @param[in] thread: 某個線程的ID  
 *  
 * @return 成功時返回0,失敗返回其他值  
 */  
int pthread_detach(pthread_t thread);

pthread_create創建的線程有兩種狀態:joinable(可結合的)和unjoinable(不可結合的/分離的)。默認是joinable 狀態。

一個可結合的線程能夠被其他線程收回其資源和殺死;在被其他線程回收之前,它的存儲器資源(如棧)是不釋放的,所以以默認的屬性創建線程時,創建的線程時可結合的,我們需要對線程退出時調用pthread_join對線程資源進行回收。只有當pthread_join函數返回時,創建的線程才算終止,才能釋放自己占用的系統資源。

一個不可結合的線程,線程結束后會自動釋放占用資源。

因為pthread_join是一個阻塞的操作,而大多數時候主線程并不希望因為調用pthread_join而阻塞,并且大多數情況下不會使用線程函數體的返回值,所以這時候可以把線程創建為不可結合的/分離的。

把線程創建為不可結合的/分離的有兩種方式:

  • 在創建線程之后,使用pthraad_detach分離線程。
  • 在創建線程之前,使用pthread_attr_setdetachstate設置線程以不可結合的/分離的狀態創建。

例子:在創建線程之后,使用pthraad_detach分離線程。

#include < stdio.h >  
#include < stdlib.h >  
#include < unistd.h >  
#include < pthread.h >  
  
static pthread_t s_thread_id;  
static unsigned char s_thread_running = 0;  
  
void *thread_fun(void *arg)  
{  
    s_thread_running = 1;  
    while (s_thread_running)  
    {  
        printf("child thread run...\\n");  
        sleep(1);  
    }  
  
    pthread_exit(NULL);  
}  
  
int main(void)  
{  
    int ret = 0;  
  
    printf("Before Thread\\n");  
    ret = pthread_create(&s_thread_id, NULL, thread_fun, NULL);  
    if (ret != 0)  
    {  
        printf("thread_create error!\\n");  
        exit(EXIT_FAILURE);  
    }  
  
    ret = pthread_detach(s_thread_id);  
    if (ret != 0)  
    {  
        printf("pthread_detach error!\\n");  
        exit(EXIT_FAILURE);  
    }  
    printf("After Thread\\n");  
  
    while (1)  
    {  
        printf("main thread run...\\n");  
        sleep(1);  
    }  
      
    exit(EXIT_SUCCESS);  
}

編譯、運行:

image.png

pthread_join與pthraad_detach的區別:

  • pthread_detach()即主線程與子線程分離,兩者相互不干涉,子線程結束同時子線程的資源自動回收。
  • pthread_join()即是子線程合入主線程,主線程會一直阻塞,直到子線程執行結束,然后回收子線程資源,并繼續執行。

6、pthread_attr_init

`/**  
 * @brief 初始化一個線程對象的屬性  
 *  
 * Detailed function description  
 *  
 * @param[in] attr: 指向一個線程屬性的指針  
 *  
 * @return 成功時返回0,失敗返回其他值  
 */  
int pthread_attr_init(pthread_attr_t *attr);  
`

如果不設置線程屬性,線程則以默認屬性進行創建,默認的屬性值如:

image.png

例子:在創建線程之前,使用pthread_attr_setdetachstate設置線程以不可結合的/分離的狀態創建。

`#include < stdio.h >  
#include < stdlib.h >  
#include < unistd.h >  
#include < pthread.h >  
  
static pthread_t s_thread_id;  
static unsigned char s_thread_running = 0;  
  
void *thread_fun(void *arg)  
{  
    s_thread_running = 1;  
    while (s_thread_running)  
    {  
        printf("thread run...\\n");  
        sleep(1);  
    }  
  
    pthread_exit(NULL);  
}  
  
int main(void)  
{  
    int ret = 0;  
  
    printf("Before Thread\\n");  
    pthread_attr_t attr;  
    ret = pthread_attr_init(&attr);  
    if (ret != 0)  
    {  
        printf("pthread_attr_init error!\\n");  
        exit(EXIT_FAILURE);  
    }  
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  ///< 線程以分離的狀態創建  
    ret = pthread_create(&s_thread_id, &attr, thread_fun, NULL);  
    if (ret != 0)  
    {  
        printf("thread_create error!\\n");  
        exit(EXIT_FAILURE);  
    }  
    printf("After Thread\\n");  
    pthread_attr_destroy(&attr);  ///< 銷毀線程屬性結構  
  
    while (1)  
    {  
        sleep(1);  
    }  
      
    exit(EXIT_SUCCESS);  
}  
`

二、互斥鎖(mutex)的使用

互斥鎖用于保護一些公共資源。一些公共資源有可能會被多個線程共同使用,如果不做資源保護,可能會產生 意想不到的bug。

一個線程,如果需要訪問公共資源,需要獲得互斥鎖并對其加鎖,資源在在鎖定過程中,如果其它線程對其進行訪問,也需要獲得互斥鎖,如果獲取不到,線程只能進行阻塞,直到獲得該鎖的線程解鎖。

互斥鎖API:

`#include< pthread.h >    
///< 創建互斥對象,用指定的初始化屬性初始化互斥對象    
int pthread_mutex_init(pthread_mutex_t *mutex,    
                                       const pthread_mutex_attr_t *mutexattr);    
  
///< 加鎖    
int pthread_mutex_lock(pthread_mutex_t *mutex);    
  
///< 解鎖    
int pthread_mutex_unlock(pthread_mutex_t *mutex);    
  
///< 加鎖,但是如果對象已經上鎖則返回EBUSY錯誤代碼而不阻塞    
int pthread_mmutex_trylock(pthread_mutex_t *mutex);    
  
///< 析構并釋放mutex相關資源    
int pthread_mutex_destroy(pthread_mutex_t *mutex);    
`

互斥鎖有兩種創建方式:

  • 靜態創建:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  • 動態創建:
`pthread_mutex_t mutex;  
pthread_mutex_init(&mutex, NULL);  
`

pthread互斥鎖屬性包括:

  • PTHREAD_MUTEX_TIMED_NP:這是缺省值,也就是普通鎖。當一個線程加鎖以后,其余請求鎖的線程將會形成一個等待隊列,并在解鎖后按優先級獲得鎖。這種策略可以確保資源分配的公平性。
  • PTHREAD_MUTEX_RECURSIVE_NP:嵌套鎖。允許同一個線程對同一個鎖成功獲得多次,并通過unlock解鎖。如果是不同線程請求,則在加鎖線程解鎖時重新競爭。
  • PTHREAD_MUTEX_ERRORCHECK_NP:檢錯鎖。如果同一個線程請求同一個鎖,則返回EDEADLK,否則與PTHREAD_MUTEX_TIMED_NP類型動作相同,這樣就保證了當不允許多次加鎖時不會出現最簡單情況下的死鎖。
  • PTHREAD_MUTEX_ADAPTIVE_NP:適應鎖,動作最簡單的鎖類型,僅等待一小段時間,如果不能獲得鎖就放棄等待

互斥鎖使用形式:

`pthread_mutex_t mutex;  
pthread_mutex_init(&mutex,NULL);  ///< 初始化互斥鎖  
pthread_mutex_lock(&mutex);       ///< 加鎖  
///< 操作公共資源  
pthread_mutex_unlock(&mutex);     ///< 解鎖  
pthread_mutex_destroy(&mutex);    ///< 銷毀互斥鎖  
`

例子:

`#include < stdio.h >  
#include < stdlib.h >  
#include < unistd.h >  
#include < pthread.h >  
  
static pthread_t s_thread1_id;  
static pthread_t s_thread2_id;  
static unsigned char s_thread1_running = 0;  
static unsigned char s_thread2_running = 0;  
  
static pthread_mutex_t s_mutex;  
static int s_cnt = 0;  
  
void *thread1_fun(void *arg)  
{  
     printf("[%s]pthread_mutex_lock ------ s_cnt = %d\\n", __FUNCTION__, s_cnt);  
    pthread_mutex_lock(&s_mutex);    ///< 加鎖  
    for (size_t i = 0; i < 100; i++)  
    {  
        s_cnt++;  
    }  
    printf("[%s]pthread_mutex_unlock ------ s_cnt = %d\\n", __FUNCTION__, s_cnt);  
    pthread_mutex_unlock(&s_mutex);  ///< 解鎖  
      
    pthread_exit(NULL);  
}  
  
void *thread2_fun(void *arg)  
{  
    printf("[%s]pthread_mutex_lock ------ s_cnt = %d\\n", __FUNCTION__, s_cnt);  
    pthread_mutex_lock(&s_mutex);    ///< 加鎖  
    for (size_t i = 0; i < 100; i++)  
    {  
        s_cnt++;  
    }  
    printf("[%s]pthread_mutex_unlock ------ s_cnt = %d\\n", __FUNCTION__, s_cnt);  
    pthread_mutex_unlock(&s_mutex);  ///< 解鎖  
      
    pthread_exit(NULL);  
}  
  
int main(void)  
{  
    int ret = 0;  
  
    ///< 創建互斥量  
    ret = pthread_mutex_init(&s_mutex, NULL);  
    if (ret != 0)  
    {  
        printf("pthread_mutex_init error!\\n");  
        exit(EXIT_FAILURE);  
    }  
  
    ///< 創建線程1  
    ret = pthread_create(&s_thread1_id, NULL, thread1_fun, NULL);  
    if (ret != 0)  
    {  
        printf("thread1_create error!\\n");  
        exit(EXIT_FAILURE);  
    }  
    ret = pthread_join(s_thread1_id, NULL); ///< 阻塞等待線程結束  
    if (ret != 0)  
    {  
        printf("pthread1_join error!\\n");  
        exit(EXIT_FAILURE);  
    }  
  
    ///< 創建線程2  
    ret = pthread_create(&s_thread2_id, NULL, thread2_fun, NULL);  
    if (ret != 0)  
    {  
        printf("thread2_create error!\\n");  
        exit(EXIT_FAILURE);  
    }  
    ret = pthread_join(s_thread2_id, NULL); ///< 阻塞等待線程結束  
    if (ret != 0)  
    {  
        printf("pthread2_join error!\\n");  
        exit(EXIT_FAILURE);  
    }  
  
    printf("main thread, s_cnt = %d\\n", s_cnt);  
  
    ret = pthread_mutex_destroy(&s_mutex);  
    {  
        printf("pthread_mutex_destroy error!\\n");  
        exit(EXIT_FAILURE);  
    }  
  
    return 0;  
}  
`

編譯、運行:

image.png

三、條件變量的使用

條件變量是在線程中以睡眠的方式等待某一條件的發生,是利用線程間共享的全局變量進行同步的一種機制。

條件變量是線程可用的一種同步機制,條件變量給多個線程提供了一個會合的場所,條件變量與互斥量一起使用時,允許線程以無競爭的方式等待特定的條件發生。

條件變量API:

#include < pthread.h >  
///< 條件變量初始化  
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);  
  
///< 銷毀條件變量  
int pthread_cond_destroy(pthread_cond_t *cond);  
  
///< 等待條件變量  
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);  
  
///< 帶有超時功能的 等待條件變量  
int pthread_cond_timedwait(pthread_cond_t *restrict cond,   
      pthread_mutex_t *restrict mutex,  
      const struct timespec *restrict tsptr);  
  
///< 通知條件變量,喚醒至少1個等待該條件的線程  
int pthread_cond_signal(pthread_cond_t *cond);  
  
///< 通知條件變量,廣播喚醒等待該條件的所有線程  
int pthread_cond_broadcast(pthread_cond_t *cond);

假如有兩個線程,線程1依賴于某個變量才能執行相應的操作,而這個變量正好是由線程2來改變的。這種情況下有兩種方案編寫程序:

方案一:線程1輪詢的方式檢測這個變量是否變化,變化則執行相應的操作。

方案二:使用條件變量的方式。線程1等待線程2滿足條件時進行喚醒。

其中,方案一比較浪費CPU資源。

條件變量的例子:創建兩個線程,線程1對全局計數變量cnt從0開始進行自增操作。線程2打印5的倍數,線程1打印其它數。

`#include < stdio.h >  
#include < stdlib.h >  
#include < unistd.h >  
#include < pthread.h >  
  
static pthread_t s_thread1_id;  
static pthread_t s_thread2_id;  
static unsigned char s_thread1_running = 0;  
static unsigned char s_thread2_running = 0;  
  
static pthread_mutex_t s_mutex;  
static pthread_cond_t s_cond;  
static int s_cnt = 0;  
  
void *thread1_fun(void *arg)  
{  
    s_thread1_running = 1;  
    while (s_thread1_running)    
    {  
        pthread_mutex_lock(&s_mutex);    ///< 加鎖  
        s_cnt++;  
        pthread_mutex_unlock(&s_mutex);  ///< 解鎖  
  
        if (s_cnt % 5 == 0)  
        {  
            pthread_cond_signal(&s_cond);  ///< 喚醒其它等待該條件的線程  
        }  
        else  
        {  
            printf("[%s]s_cnt = %d\\n", __FUNCTION__, s_cnt);  
        }  
  
        usleep(100 * 1000);  
    }  
      
    pthread_exit(NULL);  
}  
  
void *thread2_fun(void *arg)  
{  
    s_thread2_running = 1;  
    while (s_thread2_running)  
    {  
        pthread_mutex_lock(&s_mutex);    ///< 加鎖  
        while (s_cnt % 5 != 0)  
        {  
            pthread_cond_wait(&s_cond, &s_mutex);   ///< 等待條件變量  
        }  
          
        printf("[%s]s_cnt = %d\\n", __FUNCTION__, s_cnt);  
        pthread_mutex_unlock(&s_mutex);  ///< 解鎖  
          
        usleep(200 * 1000);  
    }  
      
    pthread_exit(NULL);  
}  
  
int main(void)  
{  
    int ret = 0;  
  
    ///< 創建互斥量  
    ret = pthread_mutex_init(&s_mutex, NULL);  
    if (ret != 0)  
    {  
        printf("pthread_mutex_init error!\\n");  
        exit(EXIT_FAILURE);  
    }  
  
    ///< 創建條件變量  
    ret = pthread_cond_init(&s_cond, NULL);  
    if (ret != 0)  
    {  
        printf("pthread_cond_init error!\\n");  
        exit(EXIT_FAILURE);  
    }  
  
    ///< 創建線程1  
    ret = pthread_create(&s_thread1_id, NULL, thread1_fun, NULL);  
    if (ret != 0)  
    {  
        printf("thread1_create error!\\n");  
        exit(EXIT_FAILURE);  
    }  
    ret = pthread_detach(s_thread1_id);  
    if (ret != 0)  
    {  
        printf("s_thread1_id error!\\n");  
        exit(EXIT_FAILURE);  
    }  
  
    ///< 創建線程2  
    ret = pthread_create(&s_thread2_id, NULL, thread2_fun, NULL);  
    if (ret != 0)  
    {  
        printf("thread2_create error!\\n");  
        exit(EXIT_FAILURE);  
    }  
    ret = pthread_detach(s_thread2_id);  
    if (ret != 0)  
    {  
        printf("s_thread2_id error!\\n");  
        exit(EXIT_FAILURE);  
    }  
  
    while (1)  
    {  
        sleep(1);  
    }  
  
    return 0;  
}  
`

編譯、運行:

image.png

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux系統
    +關注

    關注

    4

    文章

    595

    瀏覽量

    27449
  • C語言
    +關注

    關注

    180

    文章

    7613

    瀏覽量

    137247
  • Pthread線程庫

    關注

    0

    文章

    5

    瀏覽量

    5951
收藏 人收藏

    評論

    相關推薦

    labview多線程編程

    子曰:何為labview多線程編程
    發表于 03-11 15:46

    Linux下多線程編程總結

    最近研究MySQL源碼,各種鎖,各種互斥,好在我去年認真學了《unix環境高級編程》, 雖然已經忘得差不多了,但是學過始終是學過,拿起來也快。寫這篇文章的目的就是總結Linux 下多線程編程
    發表于 07-23 08:17

    C++面向對象多線程編程 (pdf電子版)

    C++面向對象多線程編程共分13章,全面講解構建多線程架構與增量多線程編程技術。第1章介紹了
    發表于 09-25 09:39 ?0次下載

    QNX環境下多線程編程

    介紹了QNX 實時操作系統和多線程編程技術,包括線程間同步的方法、多線程程序的分析步驟、線程基本程序結構以及實用編譯方法。QNX 是由加拿大
    發表于 08-12 17:37 ?30次下載

    linux多線程編程課件

    電子發燒友為您提供了linux多線程編程課件,希望對您學習 linux 有所幫助。部分內容如下: *1、多線程模型在單處理器模型和多處理器系統上,都能改善響應時間和吞吐量。 *2、線程
    發表于 07-10 11:58 ?0次下載

    linux多線程編程開發

    本文中我們針對 Linux 上多線程編程的主要特性總結出 5 條經驗,用以改善 Linux 多線程編程的習慣和避免其中的開發陷阱。在本文中,
    發表于 12-26 14:24 ?55次下載
    linux<b class='flag-5'>多線程</b><b class='flag-5'>編程</b>開發

    MFC下的多線程編程

    計算機上的上位機制作工具語言之MFC下的多線程編程
    發表于 09-01 14:55 ?0次下載

    VC-MFC多線程編程詳解

    VC編程中關于 MFC多線程編程的詳解文檔
    發表于 09-01 15:01 ?0次下載

    Windows多線程編程

    計算機上的上位機制作工具語言之Windows多線程編程,感興趣的可以看看。
    發表于 09-01 15:27 ?0次下載

    什么是多線程編程?多線程編程基礎知識

    摘要:多線程編程是現代軟件技術中很重要的一個環節。要弄懂多線程,這就要牽涉到多進程。本文主要以多線程編程以及
    發表于 12-08 16:30 ?1.3w次閱讀

    關于Linux下多線程編程技術學習總結

    Linux下多線程編程技術 作為一個IT人員,不斷的學習和總結是我們這個職業習慣,所以我會將每個階段的學習都會通過一點的總結來記錄和檢測自己的學習效果,今天為大家
    發表于 04-22 03:12 ?2216次閱讀
    關于Linux下<b class='flag-5'>多線程</b><b class='flag-5'>編程</b>技術學習<b class='flag-5'>總結</b>

    多線程編程指南的PDF電子書免費下載

    多線程編程指南》介紹了 SolarisTM 操作系統 (Solaris Operating System, Solaris OS)中 POSIX?線程和 Solaris 線程
    發表于 06-11 08:00 ?4次下載
    <b class='flag-5'>多線程</b><b class='flag-5'>編程</b>指南的PDF電子書免費下載

    Linux中多線程編程知識

    Hello、Hello大家好,我是木榮,今天我們繼續來聊一聊Linux中多線程編程中的重要知識點,詳細談談多線程中同步和互斥機制。
    發表于 04-26 17:27 ?615次閱讀
    Linux中<b class='flag-5'>多線程</b><b class='flag-5'>編程</b>的<b class='flag-5'>知識</b>點

    mfc多線程編程實例

    (圖形用戶界面)應用程序的開發。在這篇文章中,我們將重點介紹MFC中的多線程編程多線程編程在軟件開發中非常重要,它可以實現程序的并發執行,提高程序的效率和響應速度。MFC提供了豐富
    的頭像 發表于 12-01 14:29 ?1537次閱讀

    socket 多線程編程實現方法

    在現代網絡編程中,多線程技術被廣泛應用于提高服務器的并發處理能力。Socket編程是網絡通信的基礎,而將多線程技術應用于Socket編程,可
    的頭像 發表于 11-12 14:16 ?411次閱讀
    主站蜘蛛池模板: 99久久免费精品视频| 777人体粉嫩u美图| 色妞导航| 色偷偷网| 欧洲综合色| 精品女视频在线观看免费| 二级特黄绝大片免费视频大片 | 欧美日韩高清一区| 另类性欧美喷潮videofree| 婷婷色婷婷| 色性网| 欧美18性精品| 国产精品资源在线播放| 97理论三级九七午夜在线观看| 午夜美女影院| 国产黄色片一级| 亚洲一级免费视频| 一级片视频在线| 日本四虎影院| 国产精品嫩草影院一二三区入口| 91噜噜噜| 九九精品在线| 亚洲视频在线观看一区| 国产黄色录像视频| 中国一级生活片| 伊人久久成人成综合网222| 日韩美aaa特级毛片| 国产色爽女小说免费看| 天天做天天看夜夜爽毛片| 国产精品嫩草影院人体模特| 亚洲一区二区三区免费在线观看| 亚洲性人人天天夜夜摸| 欧美一区二区三区免费| www.四虎影院在线观看| 久久波多野结衣| 男人一级片| 日韩一级免费视频| 丁香六月色婷婷| 国内精品网站| 妇女交性大片| 欧美天天视频|