Linux系統編程-線程同步詳解

線程同步是指多個線程協調工作,以便在共享資源的訪問和操作過程中保持數據一致性和正確性。在多線程環境中,線程是并發執行的,因此如果多個線程同時訪問和修改共享資源,可能會導致數據不一致、競態條件(race condition)等問題。線程同步通過協調線程的執行順序和共享資源的訪問來避免這些問題。

在多線程編程中,需要線程同步的主要原因包括:

  • 共享資源的安全訪問:多個線程可能同時訪問和修改共享的數據或資源,如果沒有同步機制,可能會導致數據不一致或損壞。

  • 避免競態條件:競態條件是指多個線程以不受控制的順序訪問共享資源,從而導致程序執行結果不確定的情況。通過同步機制可以避免競態條件的發生。

  • 保證程序正確性:線程同步確保多線程程序的行為是可預測和正確的,避免因并發訪問而引入的錯誤。

1.互斥量(Mutex)

互斥量(互斥鎖)是一種最基本的同步機制,用于保護臨界區(Critical Section),確保在同一時間只有一個線程可以訪問共享資源。

它提供了兩個主要操作:

  • 加鎖(Locking):線程通過加鎖操作獲取互斥量,如果互斥量已經被其他線程鎖定,則當前線程會阻塞,直到獲取到鎖。
  • 解鎖(Unlocking):線程使用解鎖操作釋放互斥量,允許其他線程獲取鎖。

通過這種機制,互斥量確保了臨界區中的代碼在同一時間只能被一個線程執行,從而避免了數據競爭和不一致的問題。

1.1初始化和銷毀互斥量

1.1.1pthread_mutex_init()

初始化互斥量,并可選地設置其屬性。

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
參數:
pthread_mutex_t *mutex:指向互斥量變量的指針,用于初始化該互斥量。
const pthread_mutexattr_t *attr:可選參數,指向 pthread_mutexattr_t 類型的指針,用于設置互斥量的屬性。如果為 NULL,使用默認屬性。
返回值:
成功:返回 0。
失敗:返回錯誤號(例如 EINVAL 表示參數無效)。
  • 初始化互斥量后需要調用 pthread_mutex_destroy 函數來釋放其占用的資源。
  • 通常在使用互斥量前調用,確保互斥量的準備和設置。

1.1.2pthread_mutex_destroy()

銷毀互斥量,釋放其占用的資源。

int pthread_mutex_destroy(pthread_mutex_t *mutex);
參數:
pthread_mutex_t *mutex:指向要銷毀的互斥量變量的指針。
返回值:
成功:返回 0。
失敗:返回錯誤號。
  • 在互斥量不再需要時調用,以釋放其占用的資源。
  • 僅當確保沒有線程在使用該互斥量時才能安全地調用該函數。

1.2加鎖和解鎖操作

1.2.1pthread_mutex_lock()

加鎖操作,阻塞當前線程直到獲取鎖。

int pthread_mutex_lock(pthread_mutex_t *mutex);
參數:
pthread_mutex_t *mutex:指向要加鎖的互斥量變量的指針。
返回值:
成功:返回 0。
失敗:返回錯誤號。
  • 當互斥量已經被其他線程鎖定時,當前線程會阻塞直到獲取鎖。
  • 必須成對使用 pthread_mutex_lockpthread_mutex_unlock 來保護臨界區。

1.2.2pthread_mutex_trylock()

嘗試加鎖操作,非阻塞式,立即返回結果。

int pthread_mutex_trylock(pthread_mutex_t *mutex);
參數:
pthread_mutex_t *mutex:指向要加鎖的互斥量變量的指針。
返回值:
成功:返回 0。
失敗:返回 EBUSY(互斥量已被鎖定)或其他錯誤號。
  • 如果互斥量已被鎖定,則立即返回錯誤。
  • 適用于需要非阻塞嘗試加鎖的情況,可以用于避免線程阻塞。

1.2.3pthread_mutex_unlock()

解鎖操作,釋放互斥量。

int pthread_mutex_unlock(pthread_mutex_t *mutex);
參數:
pthread_mutex_t *mutex:指向要解鎖的互斥量變量的指針。
返回值:
成功:返回 0。
失敗:返回錯誤號。
  • 解鎖后允許其他線程獲取互斥量。
  • 必須在每次成功調用 pthread_mutex_lock 后調用 pthread_mutex_unlock 來釋放鎖。

示例代碼:

創建兩個線程來共享一個全局變量 int number,然后每個線程分別對其進行5000次遞增操作,同時使用互斥量來保證線程同步。(如果沒有鎖大家可以看看會發生什么情況)

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>#define NUM_THREADS 2
#define NUM_INCREMENTS 5000int number = 0;
pthread_mutex_t mutex;  // 互斥量變量void* thread_function(void* arg) {int thread_id = *(int*)arg;for (int i = 0; i < NUM_INCREMENTS; ++i) {// 加鎖pthread_mutex_lock(&mutex);// 臨界區:對共享變量 number 執行操作number++;// 解鎖pthread_mutex_unlock(&mutex);}pthread_exit(NULL);
}int main() {pthread_t threads[NUM_THREADS];int thread_ids[NUM_THREADS];// 初始化互斥量if (pthread_mutex_init(&mutex, NULL) != 0) {fprintf(stderr, "Mutex initialization failed\n");return 1;}// 創建兩個線程for (int i = 0; i < NUM_THREADS; ++i) {thread_ids[i] = i;if (pthread_create(&threads[i], NULL, thread_function, &thread_ids[i]) != 0) {fprintf(stderr, "Thread creation failed\n");return 1;}}// 等待所有線程結束for (int i = 0; i < NUM_THREADS; ++i) {pthread_join(threads[i], NULL);}// 銷毀互斥量pthread_mutex_destroy(&mutex);// 輸出最終的 number 值printf("Final value of number: %d\n", number);return 0;
}

1.3死鎖(Deadlock)

死鎖并不是linux提供給用戶的一種使用方法,而是由于用戶使用互斥鎖不當引起的一種現象。死鎖發生在多個并發執行的線程(或進程)之間,主要由于彼此競爭資源而造成。典型的死鎖情況涉及兩個或多個線程或進程,每個都在等待對方釋放其持有的資源,導致所有線程都被阻塞,無法繼續執行下去。

常見的死鎖有兩種:

第一種:自己鎖自己,如下圖代碼片段

第二種 線程A擁有A鎖,請求獲得B鎖;線程B擁有B鎖,請求獲得A鎖,這樣造成線程A和線程B都不釋放自己的鎖,而且還想得到對方的鎖,從而產生死鎖,如下圖所示:

  • 如何解決死鎖:
  • 讓線程按照一定的順序去訪問共享資源
  • 在訪問其他鎖的時候,需要先將自己的鎖解開
  • 調用pthread_mutex_trylock,如果加鎖不成功會立刻返回

2. 條件變量(Condition Variable)

條件變量(Condition Variable) 是一種線程間同步的機制,通常與互斥鎖結合使用,用于在某個條件滿足時通知其他線程。條件變量允許線程在等待某個特定條件的同時阻塞,直到另一個線程顯式地通知條件已經滿足或者超時。條件本身不是鎖!但它也可以造成線程阻塞。通常與互斥鎖配合使用。給多線程提供一個會合的場所。

  • 使用互斥量保護共享數據。
  • 使用條件變量可以使線程阻塞, 等待某個條件的發生, 當條件滿足的時候解除阻塞。

主要作用包括:

  • 等待條件:使線程能夠在滿足特定條件之前進入休眠狀態,節省系統資源。
  • 條件滿足時通知:一旦其他線程改變了條件,可以通過條件變量通知正在等待的線程繼續執行。

2.1相關操作函數

2.1.1pthread_cond_init()

初始化條件變量 cond

int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
參數:
pthread_cond_t *restrict cond:指向要初始化的條件變量的指針。
const pthread_condattr_t *restrict attr:可選參數,指向 pthread_condattr_t 類型的指針,用于設置條件變量的屬性。通常可以設置為 NULL,表示使用默認屬性。
返回值:
成功:返回 0。
失敗:返回錯誤號(例如 EINVAL 表示參數無效)。
  • 初始化條件變量后,應當使用 pthread_cond_destroy 函數來釋放其占用的資源。
  • 通常在創建條件變量后立即調用該函數進行初始化。

2.1.2pthread_cond_destroy()

銷毀條件變量 cond,釋放其占用的資源。

int pthread_cond_destroy(pthread_cond_t *cond);
參數:
pthread_cond_t *cond:指向要銷毀的條件變量的指針。
返回值:
成功:返回 0。
失敗:返回錯誤號。
  • 在條件變量不再需要時調用,以釋放其占用的資源。
  • 確保沒有線程在使用該條件變量時才能安全地調用該函數。

2.1.3pthread_cond_wait()

阻塞當前線程,等待條件變量 cond 被其他線程信號喚醒。

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
參數:
pthread_cond_t *restrict cond:指向要等待的條件變量的指針。
pthread_mutex_t *restrict mutex:與條件變量相關聯的互斥鎖,用于避免競態條件。
返回值:
成功:返回 0。
失敗:返回錯誤號。
  • 調用該函數前必須先獲取 mutex 鎖,函數內部會自動釋放 mutex 鎖,并在等待期間阻塞當前線程。
  • 當被喚醒時,函數內部會再次獲取 mutex 鎖,并從函數返回。

2.1.4pthread_cond_timedwait()

在指定的超時時間內阻塞當前線程,等待條件變量 cond 被其他線程信號喚醒。

int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
參數:
pthread_cond_t *restrict cond:指向要等待的條件變量的指針。
pthread_mutex_t *restrict mutex:與條件變量相關聯的互斥鎖。
const struct timespec *restrict abstime:指定的超時時間,為絕對時間。
返回值:
成功:返回 0。
失敗:返回錯誤號。
  • pthread_cond_wait 類似,但可以設置超時時間,在超時之后會自動返回并解除阻塞。
  • 如果超時時間設置為 NULL,則函數將無限期地等待,直到條件變量被信號喚醒。

2.1.5pthread_cond_signal()

喚醒等待在條件變量 cond 上的一個線程。

int pthread_cond_signal(pthread_cond_t *cond);
參數:
pthread_cond_t *cond:指向要喚醒的條件變量的指針。
返回值:
成功:返回 0。
失敗:返回錯誤號。
  • 喚醒等待在條件變量上的一個線程,如果有多個線程等待,則可能喚醒任意一個。
  • 喚醒后,被喚醒的線程將嘗試重新獲取與條件變量關聯的互斥鎖。

示例代碼:

3. 讀寫鎖(Read-Write Lock)

讀寫鎖允許多個線程同時對共享資源進行讀取操作,但是寫操作時需要排他性,即同一時刻只能有一個線程進行寫操作。這種區分讀和寫的方式能夠有效地提高系統的并發性能,特別適用于數據結構中讀操作遠遠多于寫操作的情況。當讀寫鎖以讀模式鎖住時,它是以共享模式鎖住的;當它以寫模式鎖住時,它是以獨占模式鎖住的。寫獨占、讀共享。

讀寫鎖特性:

  • 讀寫鎖是“寫模式加鎖”時,解鎖前,所有對該鎖加鎖的線程都會被阻塞。
  • 讀寫鎖是“讀模式加鎖”時,如果線程以讀模式對其加鎖會成功;如果線程以寫模式加鎖會阻塞。
  • 讀寫鎖是“讀模式加鎖”時, 既有試圖以寫模式加鎖的線程,也有試圖以讀模式加鎖的線程。那么讀寫鎖會阻塞隨后的讀模式鎖請求。優先滿足寫模式鎖。讀鎖、寫鎖并行阻塞,寫鎖優先級高

3.1初始化和銷毀讀寫鎖

3.1.1pthread_rwlock_init()

初始化讀寫鎖 rwlock,可以選擇性地設置其屬性。

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
參數:
pthread_rwlock_t *restrict rwlock:指向要初始化的讀寫鎖變量的指針。
const pthread_rwlockattr_t *restrict attr:可選參數,指向 pthread_rwlockattr_t 類型的指針,用于設置讀寫鎖的屬性。通常可以設置為 NULL,表示使用默認屬性。
返回值:
成功:返回 0。
失敗:返回錯誤號(例如 EINVAL 表示參數無效)。
  • 初始化讀寫鎖后,應當使用 pthread_rwlock_destroy 函數來釋放其占用的資源。
  • 通常在創建讀寫鎖后立即調用該函數進行初始化。

3.1.2pthread_rwlock_destroy()

銷毀讀寫鎖 rwlock,釋放其占用的資源。

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
參數:
pthread_rwlock_t *rwlock:指向要銷毀的讀寫鎖變量的指針。
返回值:
成功:返回 0。
失敗:返回錯誤號。
  • 在讀寫鎖不再需要時調用,以釋放其占用的資源。
  • 確保沒有線程在使用該讀寫鎖時才能安全地調用該函數。

3.2讀寫鎖加鎖和解鎖操作:

3.2.1pthread_rwlock_rdlock()

加讀鎖,允許多個線程同時對共享資源進行讀取操作。

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
參數:
pthread_rwlock_t *rwlock:指向要加讀鎖的讀寫鎖變量的指針。
返回值:
成功:返回 0。
失敗:返回錯誤號。
  • 如果有其他線程持有寫鎖或者有線程在請求寫鎖,則當前線程將被阻塞,直到獲取讀鎖為止。
  • 多個線程可以同時獲取讀鎖,不會相互阻塞。

3.2.2pthread_rwlock_wrlock()

加寫鎖,確保只有一個線程可以對共享資源進行寫操作,期間禁止其他線程的讀或寫操作。

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
參數:
pthread_rwlock_t *rwlock:指向要加寫鎖的讀寫鎖變量的指針。
返回值:
成功:返回 0。
失敗:返回錯誤號。
  • 如果有其他線程持有讀鎖或寫鎖,則當前線程將被阻塞,直到獲取寫鎖為止。
  • 只能有一個線程可以同時持有寫鎖,其他線程無法同時獲取讀鎖或寫鎖。

3.2.3pthread_rwlock_tryrdlock()

嘗試加讀鎖,非阻塞方式。如果不能立即獲得鎖,則立即返回。

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
參數:
pthread_rwlock_t *rwlock:指向要加讀鎖的讀寫鎖變量的指針。
返回值:
成功:返回 0。
失敗:返回 EBUSY(讀寫鎖已被寫鎖占用)或其他錯誤號。
  • 如果不能立即獲取讀鎖,則該函數立即返回失敗。
  • 適用于需要檢測是否可以立即讀取共享資源的場景。

3.2.4pthread_rwlock_trywrlock()

嘗試加寫鎖,非阻塞方式。如果不能立即獲得鎖,則立即返回。

int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
參數:
pthread_rwlock_t *rwlock:指向要加寫鎖的讀寫鎖變量的指針。
返回值:
成功:返回 0。
失敗:返回 EBUSY(讀寫鎖已被其他線程占用)或其他錯誤號。
  • 如果不能立即獲取寫鎖,則該函數立即返回失敗。
  • 適用于需要檢測是否可以立即寫入共享資源的場景。

3.2.5pthread_rwlock_unlock()

解鎖操作,釋放之前加的讀鎖或寫鎖。

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
參數:
pthread_rwlock_t *rwlock:指向要解鎖的讀寫鎖變量的指針。
返回值:
成功:返回 0。
失敗:返回錯誤號。
  • 解鎖后允許其他線程獲取讀鎖或寫鎖。
  • 必須在每次成功調用 pthread_rwlock_rdlockpthread_rwlock_wrlock 后調用該函數來釋放鎖。

示例代碼:

其中包括3個寫線程和5個讀線程對同一個全局資源進行操作。每個線程都會不定時地訪問和修改這個全局資源,并通過讀寫鎖確保線程之間的同步。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h> // 用于隨機睡眠時間#define NUM_READERS 5
#define NUM_WRITERS 3pthread_rwlock_t rwlock;
int global_resource = 0;void* writer(void* arg) {int thread_id = *(int*)arg;while (1) {// 模擬寫操作sleep(rand() % 3); // 隨機睡眠時間// 加寫鎖pthread_rwlock_wrlock(&rwlock);// 寫操作global_resource++;printf("Writer %d writes: global_resource = %d\n", thread_id, global_resource);// 解鎖pthread_rwlock_unlock(&rwlock);}return NULL;
}void* reader(void* arg) {int thread_id = *(int*)arg;while (1) {// 模擬讀操作sleep(rand() % 2); // 隨機睡眠時間// 加讀鎖pthread_rwlock_rdlock(&rwlock);// 讀操作printf("Reader %d reads: global_resource = %d\n", thread_id, global_resource);// 解鎖pthread_rwlock_unlock(&rwlock);}return NULL;
}int main() {pthread_t writers[NUM_WRITERS], readers[NUM_READERS];int writer_ids[NUM_WRITERS], reader_ids[NUM_READERS];int i;// 初始化讀寫鎖pthread_rwlock_init(&rwlock, NULL);// 創建寫線程for (i = 0; i < NUM_WRITERS; ++i) {writer_ids[i] = i + 1;pthread_create(&writers[i], NULL, writer, &writer_ids[i]);}// 創建讀線程for (i = 0; i < NUM_READERS; ++i) {reader_ids[i] = i + 1;pthread_create(&readers[i], NULL, reader, &reader_ids[i]);}// 等待所有寫線程結束for (i = 0; i < NUM_WRITERS; ++i) {pthread_join(writers[i], NULL);}// 等待所有讀線程結束for (i = 0; i < NUM_READERS; ++i) {pthread_join(readers[i], NULL);}// 銷毀讀寫鎖pthread_rwlock_destroy(&rwlock);return 0;
}

4. 信號量(Semaphore)

信號量是由一個整型變量和相關的操作集合組成,用于控制對共享資源的訪問。信號量可以看作是一個計數器,用于表示可用的資源數量,線程或進程在訪問資源前必須首先獲取信號量,訪問結束后釋放信號量。

主要作用包括:

  • 同步:控制多個線程或進程的執行順序,保證在某些條件下的有序執行。
  • 互斥:保證對共享資源的訪問是排他的,避免多個線程或進程同時修改資源造成的數據不一致性問題。

4.2相關操作函數

4.2.1sem_init()

初始化一個信號量 sem

int sem_init(sem_t *sem, int pshared, unsigned int value);
參數:
sem_t *sem:指向要初始化的信號量的指針。
int pshared:指定信號量是進程共享(非零)還是線程共享(零)。
unsigned int value:信號量的初始值,表示可用資源的數量。
返回值:
成功:返回 0。
失敗:返回 -1,并設置 errno 來指示錯誤原因。
  • 信號量初始化后需要通過 sem_destroy 函數進行清理。
  • 如果 pshared 是非零,則信號量可以在多個進程間共享,通常使用在進程間通信(IPC)的場景中。

4.2.2sem_destroy()

銷毀一個已經初始化的信號量 sem。釋放由信號量占用的資源,確保在信號量不再需要時調用。

int sem_destroy(sem_t *sem);
參數:
sem_t *sem:指向要銷毀的信號量的指針。
返回值:
成功:返回 0。
失敗:返回 -1,并設置 errno 來指示錯誤原因。

4.2.3.sem_wait()

對信號量 sem 進行 P 操作(等待操作)。

int sem_wait(sem_t *sem);
參數:
sem_t *sem:指向要操作的信號量的指針。
返回值:
成功:返回 0。
失敗:返回 -1,并設置 errno 來指示錯誤原因。
  • 如果信號量的值大于 0,將其遞減;否則阻塞當前線程,直到信號量的值大于 0
  • 該函數執行時需要保證線程安全,通常與互斥鎖結合使用以避免競態條件。

4.2.4sem_trywait()

嘗試對信號量 sem 進行 P 操作的非阻塞版本。與 sem_wait 不同的是,如果信號量的值為 0,立即返回而不阻塞線程。

int sem_trywait(sem_t *sem);
參數:
sem_t *sem:指向要操作的信號量的指針。
返回值:
成功:返回 0。
如果信號量的值為 0,表示資源不可用,立即返回 -1(不阻塞),并設置 errno 為 EAGAIN。
其他失敗情況返回 -1,并設置 errno 來指示錯誤原因。

4.2.5sem_post()

對信號量 sem 進行 V 操作(釋放操作)。

int sem_post(sem_t *sem);
參數:
sem_t *sem:指向要操作的信號量的指針。
返回值:
成功:返回 0。
失敗:返回 -1,并設置 errno 來指示錯誤原因。
  • 將信號量的值遞增,如果有線程因等待該信號量而被阻塞,將會喚醒其中一個線程。
  • 釋放操作通常在資源使用完畢后調用,通知其他線程可以繼續訪問該資源。

4.2.6sem_getvalue()

獲取信號量 sem 的當前值。sem_getvalue 函數可以獲取信號量的當前值,而無需對其進行修改。

int sem_getvalue(sem_t *restrict sem, int *restrict sval);
參數:
sem_t *restrict sem:指向要獲取值的信號量的指針。
int *restrict sval:用于存儲信號量當前值的整型指針。
返回值:
成功:返回 0,并將當前信號量的值存儲在 sval 中。
失敗:返回 -1,并設置 errno 來指示錯誤原因。

示例代碼:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/44807.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/44807.shtml
英文地址,請注明出處:http://en.pswp.cn/web/44807.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

面試題008-Java-SpringBoot

面試題008-Java-SpringBoot 目錄 面試題008-Java-SpringBoot題目自測題目答案1. Spring 和 Spring Boot有什么區別&#xff1f;2. Spring Boot 的主要優點是什么&#xff1f;3. 什么是Spring Boot Starter&#xff1f;4. 介紹一下SpringBootApplication注解&#xff1f;5. Spri…

【密碼學】消息認證

你發送給朋友一條消息&#xff08;內容&#xff1a;明天下午來我家吃飯&#xff09;&#xff0c;這一過程中你不想讓除你朋友以外的人看到消息的內容&#xff0c;這就叫做消息的機密性&#xff0c;用來保護消息機密性的方式被叫做加密機制。 現在站在朋友的視角&#xff0c;某一…

使用PyQt5實現添加工具欄、增加SwitchButton控件

前言&#xff1a;通過在網上找到的“電池電壓監控界面”&#xff0c;學習PyQt5中添加工具欄、增加SwitchButton控件&#xff0c;在滑塊控件右側增加文本顯示、設置界面背景顏色、修改文本控件字體顏色等。 1. 上位機界面效果展示 網絡上原圖如下&#xff1a; 自己使用PyQt5做…

springboot異常(一):springboot自定義全局異常處理

&#x1f337;1. 自定義一個異常類 自定義一個異常&#xff0c;有兩個變量異常代碼、異常消息&#xff0c;定義了兩個構造方法&#xff0c;一個無參構造方法&#xff0c;一個所有參數構造方法。 在構造方法中要掉用父類的構造方法&#xff0c;主要目的是在日志或控制臺打印異…

【Linux】多線程_3

文章目錄 九、多線程3. C11中的多線程4. 線程的簡單封裝 未完待續 九、多線程 3. C11中的多線程 Linux中是根據多線程庫來實現多線程的&#xff0c;C11也有自己的多線程&#xff0c;那它的多線程又是怎樣的&#xff1f;我們來使用一些C11的多線程。 Makefile&#xff1a; te…

Linux - 探索命令行

探索命令行 Linux命令行中的命令使用格式都是相同的: 命令名稱 參數1 參數2 參數3 ...參數之間用任意數量的空白字符分開. 關于命令行, 可以先閱讀一些基本常識. 然后我們介紹最常用的一些命令: ls用于列出當前目錄(即"文件夾")下的所有文件(或目錄). 目錄會用藍色…

面試經典題型:調用HashMap的put方法的具體執行流程

在調用put方法時時&#xff0c;有幾個關鍵點需要考慮&#xff1a; 哈希沖突的發生與解決&#xff1a; 哈希沖突指不同的鍵通過哈希函數計算得到相同的哈希值&#xff0c;導致它們應該存放在哈希表的同一個位置。解決沖突的常用方法包括開放尋址法和鏈表法&#xff08;或其升級形…

CSIP-FTE考試專業題

靶場下載鏈接&#xff1a; https://pan.baidu.com/s/1ce1Kk0hSYlxrUoRTnNsiKA?pwdha1x pte-2003密碼&#xff1a;admin123 centos:root admin123 解壓密碼&#xff1a; PTE考試專用 下載好后直接用vmware打開&#xff0c;有兩個靶機&#xff0c;一個是基礎題&#x…

【CTF-Crypto】數論基礎-02

【CTF-Crypto】數論基礎-02 文章目錄 【CTF-Crypto】數論基礎-021-16 二次剩余1-20 模p下-1的平方根*1-21 Legendre符號*1-22 Jacobi符號*2-1 群*2-2 群的性質2-3 阿貝爾群*2-4 子群2-11 群同態2-18 原根2-21 什么是環2-23 什么是域2-25 子環2-26 理想2-32 多項式環 1-16 二次剩…

打造智慧校園德育管理,提升學生操行基礎分

智慧校園的德育管理系統內嵌的操行基礎分功能&#xff0c;是對學生日常行為規范和道德素養進行量化評估的一個創新實踐。該功能通過將抽象的道德品質轉化為具體可量化的指標&#xff0c;如遵守紀律、尊師重道、團結協作、愛護環境及參與集體活動的積極性等&#xff0c;為每個學…

醫療器械FDA |FDA網絡安全測試具體內容

醫療器械FDA網絡安全測試的具體內容涵蓋了多個方面&#xff0c;以確保醫療器械在網絡環境中的安全性和合規性。以下是根據權威來源歸納的FDA網絡安全測試的具體內容&#xff1a; 一、技術文件審查 網絡安全計劃&#xff1a;制造商需要提交網絡安全計劃&#xff0c;詳細描述產…

Matlab【光伏預測】基于雪融優化算法SAO優化高斯過程回歸GPR實現光伏多輸入單輸出預測附代碼

% 光伏預測 - 基于SAO優化的GPR % 數據準備 % 假設有多個輸入特征 X1, X2, …, Xn 和一個目標變量 Y % 假設數據已經存儲在 X 和 Y 中&#xff0c;每個變量為矩陣&#xff0c;每行表示一個樣本&#xff0c;每列表示一個特征 % 參數設置 numFeatures size(X, 2); % 輸入特征的…

Spring Boot集成easyposter快速入門Demo

1.什么是easyposter&#xff1f; easyposter是一個簡單的,便于擴展的繪制海報工具包 使用場景 在日常工作過程中&#xff0c;通常一些C端平臺會伴隨著海報生成與分享業務。因為隨著移動互聯網的迅猛發展&#xff0c;社交分享已成為我們日常生活的重要組成部分。海報分享作為…

visual studio 2019版下載以及與UE4虛幻引擎配置(過程記錄)(官網無法下載visual studio 2019安裝包)

一、概述 由于需要使用到UE4虛幻引擎&#xff0c;我使用的版本是4.27版本的&#xff0c;其官方默認的visual studio版本是2019版本的&#xff0c;相應的版本對應關系可以通過下面的官方網站對應關系查詢。https://docs.unrealengine.com/4.27/zh-CN/ProductionPipelines/Develo…

MMSegmentation筆記

如何訓練自制數據集&#xff1f; 首先需要在 mmsegmentation/mmseg/datasets 目錄下創建一個自制數據集的配置文件&#xff0c;以我的蘋果葉片病害分割數據集為例&#xff0c;創建了mmsegmentation/mmseg/datasets/appleleafseg.py 可以看到&#xff0c;這個配置文件主要定義…

python:使用matplotlib庫繪制圖像(四)

作者是跟著http://t.csdnimg.cn/4fVW0學習的&#xff0c;matplotlib系列文章是http://t.csdnimg.cn/4fVW0的自己學習過程中整理的詳細說明版本&#xff0c;對小白更友好哦&#xff01; 四、條形圖 1. 一個數據樣本的條形圖 條形圖&#xff1a;常用于比較不同類別的數量或值&…

3dmax-vray5大常用材質設置方法

3dmax云渲染平臺——渲染100 以高性價比著稱&#xff0c;是預算有限的小伙伴首選。 15分鐘0.2,60分鐘內0.8;注冊填邀請碼【7788】可領30元禮包和免費渲染券 提供了多種機器配置選擇(可以自行匹配環境)最高256G大內存機器&#xff0c;滿足不同用戶需求。 木紋材質 肌理調整&…

函數語意學(The Sematics of Function)

1、非靜態成員函數轉化為非成員函數 c 設計準則之一就是&#xff1a;非靜態成員函數至少和非成員函數有相同的效率。 也就是說下面兩個函數具有相同的效率&#xff1a; float magnitude(const Point3d * this){...}; float Point3d::magnitude(){...};以 float Point3d::mag…

練習9.5 彩票分析

練習 9.14&#xff1a;彩票 創建?個列表或元素&#xff0c;其中包含 10 個數和 5 個字 ?。從這個列表或元組中隨機選擇 4 個數或字?&#xff0c;并打印?條消息&#xff0c; 指出只要彩票上是這 4 個數或字?&#xff0c;就中?獎了。 練習 9.15&#xff1a;彩票分析 可以使…

面試題 05. 替換空格

05. 替換空格 題目描述示例 題解 題目描述 請實現一個函數&#xff0c;把字符串 s 中的每個空格替換成"%20"。 示例 示例1 輸入&#xff1a;s “We are happy.” 輸出&#xff1a;“We%20are%20happy.” 題解 class Solution { public:string replaceSpace(stri…