亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

一般而言,重入鎖和概念是什么?

一般而言,重入鎖和概念是什么?

我總是很困惑。有人會解釋可重入在不同情況下的含義嗎?以及為什么要使用可重入與非可重入?說pthread(posix)鎖定原語,它們是否可重入?使用它們時應避免哪些陷阱?互斥鎖是否重新進入?
查看完整描述

3 回答

?
炎炎設計

TA貢獻1808條經驗 獲得超4個贊

使用重入鎖,您可以編寫一個M對資源加鎖的方法,A然后M遞歸調用,或從已經持有on鎖的代碼中進行調用A。

使用非重入鎖,您將需要2個版本的M,一個可以鎖定的版本和一個不可以鎖定的版本,以及其他用于調用正確版本的邏輯。


查看完整回答
反對 回復 2019-12-10
?
ABOUTYOU

TA貢獻1812條經驗 獲得超5個贊

遞歸互斥鎖的內容和原因不應是公認的答案中描述的如此復雜的事情。


我想在網上進行一些探討后寫下我的理解。


首先,您應該意識到在談論互斥時,肯定也涉及多線程概念。(互斥鎖用于同步。如果程序中只有1個線程,則不需要互斥鎖)


其次,您應該知道普通互斥鎖和遞歸互斥鎖之間的區別。


引用APUE:


(遞歸互斥鎖是a)互斥鎖類型,它允許同一線程多次鎖定它而無需先將其解鎖。


關鍵區別在于,在同一線程內,重新鎖定遞歸鎖不會導致死鎖,也不會阻塞線程。


這是否意味著后退鎖定永遠不會導致死鎖?

不,如果您將死鎖鎖定在一個線程中但未將其解鎖,然后嘗試將其鎖定在其他線程中,它仍可能導致死鎖作為普通互斥鎖。


讓我們看一些代碼作為證明。


帶有死鎖的普通互斥鎖

#include <pthread.h>

#include <stdio.h>


pthread_mutex_t lock;



void * func1(void *arg){

    printf("thread1\n");

    pthread_mutex_lock(&lock);

    printf("thread1 hey hey\n");


}



void * func2(void *arg){

    printf("thread2\n");

    pthread_mutex_lock(&lock);

    printf("thread2 hey hey\n");

}


int main(){

    pthread_mutexattr_t lock_attr;

    int error;

//    error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);

    error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_DEFAULT);

    if(error){

        perror(NULL);

    }


    pthread_mutex_init(&lock, &lock_attr);


    pthread_t t1, t2;


    pthread_create(&t1, NULL, func1, NULL);

    pthread_create(&t2, NULL, func2, NULL);


    pthread_join(t2, NULL);


}

輸出:


thread1

thread1 hey hey

thread2

常見的死鎖示例,沒問題。


死鎖的遞歸互斥

只需取消注釋此行

error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);

并注釋掉另一行。


輸出:


thread1

thread1 hey hey

thread2

是的,遞歸互斥也會導致死鎖。


普通互斥鎖,重新鎖定在同一線程中

#include <pthread.h>

#include <stdio.h>

#include <unistd.h>


pthread_mutex_t lock;



void func3(){

    printf("func3\n");

    pthread_mutex_lock(&lock);

    printf("func3 hey hey\n");

}


void * func1(void *arg){

    printf("thread1\n");

    pthread_mutex_lock(&lock);

    func3();

    printf("thread1 hey hey\n");


}



void * func2(void *arg){

    printf("thread2\n");

    pthread_mutex_lock(&lock);

    printf("thread2 hey hey\n");

}


int main(){

    pthread_mutexattr_t lock_attr;

    int error;

//    error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);

    error = pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_DEFAULT);

    if(error){

        perror(NULL);

    }


    pthread_mutex_init(&lock, &lock_attr);


    pthread_t t1, t2;


    pthread_create(&t1, NULL, func1, NULL);

    sleep(2); 

    pthread_create(&t2, NULL, func2, NULL);


    pthread_join(t2, NULL);


}

輸出:


thread1

func3

thread2

僵局thread t1中func3。

(我sleep(2)用來使死鎖首先是由于重新鎖定而引起的func3)


遞歸互斥鎖,重新鎖定在同一線程中

再次,取消注釋遞歸互斥鎖行,并注釋掉另一行。


輸出:


thread1

func3

func3 hey hey

thread1 hey hey

thread2

僵局thread t2中func2??吹剑縡unc3完成并退出后,重新鎖定不會阻塞線程或導致死鎖。


那么,最后一個問題,我們為什么需要它?


對于遞歸函數(在多線程程序中調用,并且您要保護某些資源/數據)。


例如,您有一個多線程程序,并在線程A中調用了一個遞歸函數。您在該遞歸函數中有一些要保護的數據,因此可以使用互斥鎖機制。該函數的執行在線程A中是順序執行的,因此您一定要以遞歸方式重新鎖定互斥鎖。使用普通互斥鎖會導致死鎖。并且發明了遞歸互斥體來解決這個問題。



查看完整回答
反對 回復 2019-12-10
  • 3 回答
  • 0 關注
  • 951 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號