日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux线程同步教程,多线程同步

發(fā)布時間:2025/3/12 linux 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux线程同步教程,多线程同步 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1.linux使用多線程同步的方法

1)互斥鎖:當線程A鎖定了互斥變量時,線程B再去鎖定時就會被掛起,直到A解鎖。

注意:當線程要不斷的去輪詢檢查某個條件以判斷是否可以操作需同步的數(shù)據(jù)時,可使用條件變量提高效率。

demo如下:

#include

#include

#include

?

pthread_mutex_t mutex;

?

void *print_msg(void *arg)

{

int i = 0;

pthread_mutex_lock(&mutex); //互斥鎖加鎖

for (i = 0; i < 20; i++)

{

printf(" i = %d\n", i);

usleep(200);

}

pthread_mutex_unlock(&mutex);

?

}

?

int main()

{

pthread_t id1, id2;

pthread_mutex_init(&mutex, NULL);

pthread_create(&id1, NULL, print_msg, NULL);

pthread_create(&id2, NULL, print_msg, NULL);

pthread_join(id1, NULL); //使主線程等待該線程結束后才結束,否則主線程很快結束,該線程沒有機會執(zhí)行

pthread_join(id2, NULL);

pthread_mutex_destroy(&mutex);

?

return 0;

}

2)信號量:實際是一個整數(shù),只要信號量的value大于0,其他線程就可以sem_wait成功,成功后信號量的value減1。若value值不大于0,則sem_wait使得線程阻塞,直到sem_post釋放后value值加1,但是sem_wait返回之前還是會將此value值減1。

demo如下:

#include

#include

#include

#include

#include

#include

?

void *thread_func(void* msg);

sem_t sem;

sem_t sem_add;

?

#define MSG_SIZE 512

?

int main()

{

int res = -1;

pthread_t thread;

void *thread_result = NULL;

char msg[MSG_SIZE];

?

res = sem_init(&sem, 0, 0);

if (res == -1)

{

printf("sem init failed\n");

exit(-1);

}

?

res = sem_init(&sem_add, 0, 1);

if (res == -1)

{

printf("sem_add init failed\n");

exit(-1);

}

?

res = pthread_create(&thread, NULL, thread_func, msg);

if (res != 0)

{

printf("pthread_create failed\n");

exit(-1);

}

printf("input some text. Enter 'end' to finish...\n");

sem_wait(&sem_add);

while(strcmp("end\n", msg) != 0)

{

if (strncmp(msg, "TEST", 4) == 0)

{

strcpy(msg, "copy_data\n");

sem_post(&sem);

sem_wait(&sem_add);

}

fgets(msg, MSG_SIZE, stdin);

sem_post(&sem); //sem信號量加1,讓子線程開始執(zhí)行

sem_wait(&sem_add); //sem_add信號量減1,等待子線程處理完成

?

}

?

printf("waiting for thread to finish...\n");

res = pthread_join(thread, &thread_result);

if (res != 0)

{

printf("pthread_join faild\n");

exit(-1);

}

?

printf("thread joined\n");

?

sem_destroy(&sem);

sem_destroy(&sem_add);

exit(0);

?

return 0;

}

?

void* thread_func(void* msg)

{

char *ptr = (char*)msg;

sem_wait(&sem);

while(strcmp("end\n", ptr) != 0)

{

int i = 0;

for (; ptr[i] != '\0'; ++i )

{

if (ptr[i] >= 'a' && ptr[i] <= 'z')

{

ptr[i] -= 'a' - 'A';

}

}

printf("you input %d characters\n", i - 1);

printf("to uppercase: %s\n", ptr);

?

sem_post(&sem_add);

sem_wait(&sem);

}

sem_post(&sem_add);

pthread_exit(NULL);

}

3)條件變量:經常和互斥鎖一起使用,使用時,條件變量被用來阻塞一個線程,當條件不滿足時,線程會解開相應的互斥鎖并等待條件發(fā)生變化,一旦其他的某個線程改變了條件變量,它將通知相應的條件變量喚醒一個或多個正被此變量阻塞的線程,這些線程將重新鎖定互斥鎖并重新測試條件是否滿足。

pthread_cont_init()

pthread_cont_destroy()

pthread_cont_wait() //線程解開mutex指向的鎖并被條件變量阻塞

pthread_cont_timedwait() //多了時間參數(shù),當時間過了以后,即使條件變量不滿足,阻塞也被解除

pthread_cont_signal()/pthread_cont_broadcast //喚醒被條件變量阻塞的線程。

demo如下:

pthread1()

{

pthread_mutex_lock(lock_s);

sum++;

pthread_mutex_unlock(lock_s);

if (sum >= 100)

{

pthread_cond_signal(&cond_sum_ready);//先發(fā)送一次

}

}

pthread2()

{

pthread_mutex_lock(lock_s);

while(sum < 100)

{

pthread_cond_wait(&cond_sum_ready, &lock_s);//會先執(zhí)行pthread_MUTEX_UNLOCK進行解鎖,然后休眠

}

sum = 0;

pthread_mutex_unlock(lock_s);

}

注意:最終哪個線程接收到信號,根據(jù)優(yōu)先級來

4)讀寫鎖:可以多個線程同時占用讀模式的讀寫鎖,但是只能一個線程占用寫模式的讀寫鎖。

當讀寫鎖是寫加鎖狀態(tài)時,在這個鎖被解鎖前,所有試圖對這個鎖加鎖的線程都會被阻塞;

當讀寫鎖是讀加鎖狀態(tài)時,其他線程可以讀模式得到訪問權,但是以寫模式對它進行加鎖的線程都將被阻塞;

當讀寫鎖是在讀模式加鎖狀態(tài)時,如果有其他線程試圖以寫模式加鎖,讀寫鎖通常會阻塞隨后的讀模式鎖請求,避免讀模式鎖長期占用,而寫模式所長期阻塞;

讀寫鎖適用于對數(shù)據(jù)讀的次數(shù)比寫的次數(shù)多的情況。

API接口:

初始化和銷毀:

int pthread_rwlock_init();

int pthread rwlock_destroy();

讀加鎖、寫加鎖、解鎖:

pthread_rwlock_rdlock();

pthread_rwlock_wrlock();

pthread_rwlock_unlock();

非阻塞獲得讀鎖和寫鎖:

pthread_rwlock_tryrdlock();

pthread_rwlock_trywrlock();

demo如下

#include

#include

#include

?

#define Read_Num 2

?

pthread_rwlock_t lock;

?

class Data

{

public:

Data(int i, float f): I(i), F(f){}

int GetI()

{

return I;

}

?

float GetF()

{

return F;

}

?

private:

int I;

float F;

};

?

Data *pData = NULL;

?

void *read(void *arg)

{

int *id = (int*)arg;

while(true)

{

pthread_rwlock_rdlock(&lock);

printf(" reader %d is reading data\n", *id);

if (pData == NULL)

{

printf("data is NULL\n");

}

else

{

printf("data: I = %d, F = %f\n", pData->GetI(), pData->GetF());

}

pthread_rwlock_unlock(&lock);

}

pthread_exit(0);

}

?

void *write(void *arg)

{

while(true)

{

pthread_rwlock_wrlock(&lock); //寫鎖加鎖后,解鎖前,所有試圖對該鎖加鎖的線程都會被堵塞

printf("writer is wiriting data:\n");

if (pData == NULL)

{

pData = new Data(2, 2.2);

printf("writer is writing data: %d, %f\n", pData->GetI(), pData->GetF());

}

else

{

delete pData;

pData = NULL;

printf("wirter free the data\n");

}

pthread_rwlock_unlock(&lock);

?

}

pthread_exit(0);

}

?

int main()

{

pthread_t reader[Read_Num];

pthread_t writer;

for (int i = 0; i < Read_Num; i++)

{

pthread_create(&reader[i], NULL, read, (void*)&i);

}

pthread_create(&writer, NULL, write, NULL);

while(1)

{

sleep(1);

}

return 0;

}

2.信號量和互斥鎖之間的區(qū)別:

互斥鎖用于互斥,對資源的訪問是無序的,信號量用于同步,對資源的訪問是有序的

互斥量的加鎖和解鎖必須由同一線程對應使用,而信號量可以由一個線程釋放,另一個線程得到

3.什么情況下會產生死鎖以及怎樣避免死鎖

比如線程A,對資源M加鎖,去申請資源N;

線程B,對資源N加鎖,去申請資源M;

此種情況下會產生死鎖,要有效的避免死鎖,可使用銀行家算法:

線程A和B在使用資源的時候按照同一順序,即加鎖時按照同一順序,這樣就可以避免死鎖。

總結

以上是生活随笔為你收集整理的linux线程同步教程,多线程同步的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。