一.概述
1.POXIS介紹
??POXIS是一種操作系統接口標準,全稱為“可移植操作系統接口”。
它最初由IEEE組織制定,目的是為了使不同的操作系統之間可以互相兼容。POSIX標準定義了一系列API(應用程序接口)和命令行工具,這些API和工具規定了操作系統應該提供哪些功能,并規定了這些功能的調用方式和行為。
POSIX標準包含多個部分,主要涵蓋了文件管理、進程控制、用戶權限、系統調用等方面。
跨平臺特性:為了保證操作系統 API 的相互兼容性制定了 POSIX 標準。目前符合 POSIX 標準協議的操作系統有:UNIX、BSD、Linux、iOS、Android、SylixOS、VxWorks、RTEMS 等。
Windows操作系統支持POSIX。雖然Windows操作系統并不完全符合POSIX標準,但可以通過一些工具和庫來實現POSIX兼容性。這些工具包括Cygwin、MinGW或MSYS等,它們提供了一些POSIX函數和命令,
使得在Windows上開發和運行POSIX兼容的應用程序成為可能。
2.互斥鎖和條件變量都是進程同步機制,通常,互斥鎖是用來對資源加鎖,條件變量用來等待資源,主要包括兩個動作:
??一個線程等待"條件變量的條件成立"而掛起;
另一個線程使"條件成立"(給出條件成立信號);
由于是多線程,為了防止競爭,所以條件量一般和鎖一起使用。
二.POSIX互斥鎖和條件變量
下面均以linux系統下的使用進行舉例;
1.互斥鎖
互斥鎖是一種同步機制,用于確保同一時間只有一個線程可以訪問共享資源。在 C 語言中,互斥鎖可以通過 pthread_mutex_t 類型來表示,并可以通過 pthread_mutex_init() 函數來初始化。
1.1初始化pthread_mutex_init()
pthread_mutex_init() 函數的原型如下:
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
其中,mutex 是要初始化的互斥鎖,attr 是互斥鎖屬性。pthread_mutex_init() 函數的返回值如下:
0:成功
EAGAIN:系統資源不足
EINVAL:mutex 或 attr 為 NULL
EBUSY:mutex 已被初始化
pthread_mutex_init() 函數的用法如下:
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
在上面的代碼中,首先定義了一個互斥鎖 mutex。然后,使用 pthread_mutex_init() 函數初始化互斥鎖。
1.2加鎖pthread_mutex_lock()
pthread_mutex_lock() 函數用于鎖定互斥鎖。當一個線程試圖鎖定一個已經被鎖定的互斥鎖時,該線程將被阻塞,直到互斥鎖被解鎖。 pthread_mutex_lock() 函數的原型如下:
int pthread_mutex_lock(pthread_mutex_t *mutex);
其中,mutex 是要鎖定的互斥鎖。pthread_mutex_lock() 函數的返回值如下:
0:成功
EDEADLK:線程試圖鎖定自己已經持有的互斥鎖
EINVAL:mutex 為 NULL
pthread_mutex_lock() 函數的用法如下:
pthread_mutex_lock(&mutex);
在上面的代碼中,使用 pthread_mutex_lock() 函數鎖定互斥鎖 mutex。
1.3解鎖pthread_mutex_unlock()
pthread_mutex_unlock() 函數用于解鎖互斥鎖。當一個線程解鎖一個互斥鎖時,該互斥鎖將被釋放,并且任何被阻塞的線程都可以繼續執行。 pthread_mutex_unlock() 函數的原型如下:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
其中,mutex 是要解鎖的互斥鎖。 pthread_mutex_unlock() 函數的返回值如下:
0:成功
EINVAL:mutex 為 NULL
pthread_mutex_unlock() 函數的用法如下:
pthread_mutex_unlock(&mutex);
在上面的代碼中,使用 pthread_mutex_unlock() 函數解鎖互斥鎖 mutex。
1.4銷毀pthread_mutex_destroy()
pthread_mutex_destroy() 函數用于銷毀互斥鎖。當一個互斥鎖不再需要時,應該使用 pthread_mutex_destroy() 函數來銷毀它。 pthread_mutex_destroy() 函數的原型如下:
int pthread_mutex_destroy(pthread_mutex_t *mutex);
其中,mutex 是要銷毀的互斥鎖。 pthread_mutex_destroy() 函數的返回值如下:
0:成功
EINVAL:mutex 為 NULL
pthread_mutex_destroy() 函數的用法如下:
pthread_mutex_destroy(&mutex);
在上面的代碼中,使用 pthread_mutex_destroy() 函數銷毀互斥鎖 mutex。
1.5互斥鎖完整實例
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex;
void *thread_function(void *arg) {
??pthread_mutex_lock(&mutex);
??printf("Thread %ld has locked the mutex\n", pthread_self());
??// 訪問共享資源
??printf("Thread %ld has unlocked the mutex\n", pthread_self());
??pthread_mutex_unlock(&mutex);
??return NULL;
}
int main() {
??pthread_t thread1, thread2;
??pthread_mutex_init(&mutex, NULL);
??pthread_create(&thread1, NULL, thread_function, NULL);
??pthread_create(&thread2, NULL, thread_function, NULL);
??pthread_join(thread1, NULL);
??pthread_join(thread2, NULL);
??pthread_mutex_destroy(&mutex);
??return 0;
}
在這個例子中,創建了一個互斥鎖 mutex,并使用 pthread_mutex_init() 函數初始化它。然后,創建了兩個線程,并使用 pthread_mutex_lock() 函數鎖定互斥鎖,然后訪問共享資源。在訪問共享資源之前,打印一條消息,表明線程已經鎖定了互斥鎖。在訪問共享資源之后,打印一條消息,表明線程已經解鎖了互斥鎖。最后,使用 pthread_mutex_unlock() 函數解鎖互斥鎖,并使用 pthread_mutex_destroy() 函數銷毀互斥鎖。
2.條件變量
條件變量是一種同步機制,用于等待某個條件的發生。在 C 語言中,條件變量可以通過 pthread_cond_t 類型來表示,并可以通過 pthread_cond_init() 函數來初始化。
2.1初始化pthread_cond_init()
pthread_cond_init() 函數的原型如下:
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
其中,cond 是要初始化的條件變量,attr 是條件變量屬性。 pthread_cond_init() 函數的返回值如下:
0:成功
EAGAIN:系統資源不足
EINVAL:cond 或 attr 為 NULL
EBUSY:cond 已被初始化
pthread_cond_init() 函數的用法如下:
pthread_cond_t cond;
pthread_cond_init(&cond, NULL);
在上面的代碼中,首先定義了一個條件變量 cond。然后,我們使用 pthread_cond_init() 函數初始化條件變量。
2.2銷毀pthread_cond_destroy()
pthread_cond_destroy() 函數用于銷毀條件變量。當一個條件變量不再需要時,應該使用 pthread_cond_destroy() 函數來銷毀它。 pthread_cond_destroy() 函數的原型如下:
int pthread_cond_destroy(pthread_cond_t *cond);
其中,cond 是要銷毀的條件變量。 pthread_cond_destroy() 函數的返回值如下:
0:成功
EINVAL:cond 為 NULL
pthread_cond_destroy() 函數的用法如下:
pthread_cond_destroy(&cond);
在上面的代碼中,使用 pthread_cond_destroy() 函數銷毀條件變量 cond。
2.3喚醒pthread_cond_signal()
pthread_cond_signal() 函數用于喚醒一個正在等待條件變量的線程。當一個線程調用 pthread_cond_signal() 函數時,該線程將被喚醒,并且可以繼續執行。 pthread_cond_signal() 函數的原型如下:
int pthread_cond_signal(pthread_cond_t *cond);
其中,cond 是要喚醒的條件變量。 pthread_cond_signal() 函數的返回值如下:
0:成功
EINVAL:cond 為 NULL
pthread_cond_signal() 函數的用法如下:
pthread_cond_signal(&cond);
在上面的代碼中,我們使用 pthread_cond_signal() 函數喚醒條件變量 cond。
2.4喚醒所有pthread_cond_broadcast()
pthread_cond_broadcast() 函數用于喚醒所有正在等待條件變量的線程。當一個線程調用 pthread_cond_broadcast() 函數時,所有正在等待該條件變量的線程將被喚醒,并且可以繼續執行。 pthread_cond_broadcast() 函數的原型如下:
int pthread_cond_broadcast(pthread_cond_t *cond);
其中,cond 是要喚醒的條件變量。 pthread_cond_broadcast() 函數的返回值如下:
0:成功
EINVAL:cond 為 NULL
pthread_cond_broadcast() 函數的用法如下:
pthread_cond_broadcast(&cond);
在上面的代碼中,我們使用 pthread_cond_broadcast() 函數喚醒條件變量 cond。
2.5等待pthread_cond_timedwait()
pthread_cond_timedwait() 函數用于等待條件變量的發生。當一個線程調用 pthread_cond_timedwait() 函數時,該線程將被阻塞,直到條件變量發生或超時。
pthread_cond_timedwait() 函數的原型如下:
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
其中,cond 是要等待的條件變量,mutex 是要鎖定的互斥鎖,abstime 是超時時間。 pthread_cond_timedwait() 函數的返回值如下:
0:成功
ETIMEDOUT:超時
EINVAL:cond 或 mutex 為 NULL
EDEADLK:線程試圖鎖定自己已經持有的互斥鎖
pthread_cond_timedwait() 函數的用法如下:
pthread_cond_timedwait(&cond, &mutex, &abstime);
在上面的代碼中,我們使用 pthread_cond_timedwait() 函數等待條件變量 cond 的發生。
2.6條件變量完整實例
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 2
int count = 0;
pthread_mutex_t mutex;
pthread_cond_t cond;
void* thread_func(void* thread_id) {
????int tid = *((int*)thread_id);
????
????pthread_mutex_lock(&mutex);
????
????while (count < tid) {
????????pthread_cond_wait(&cond, &mutex);
????}
????
????printf("Thread %d: Hello, World!\n", tid);
????
????count++;
????
????pthread_cond_broadcast(&cond);
????pthread_mutex_unlock(&mutex);
????
????pthread_exit(NULL);
}
int main() {
????pthread_t threads[NUM_THREADS];
????int thread_ids[NUM_THREADS];
????
????pthread_mutex_init(&mutex, NULL);
????pthread_cond_init(&cond, NULL);
????
????for (int i = 0; i < NUM_THREADS; i++) {
????????thread_ids[i] = i;
????????pthread_create(&threads[i], NULL, thread_func, (void*)&thread_ids[i]);
????}
????
????for (int i = 0; i < NUM_THREADS; i++) {
????????pthread_join(threads[i], NULL);
????}
????
????pthread_mutex_destroy(&mutex);
????pthread_cond_destroy(&cond);
????
????return 0;
}