單線程會(huì)導(dǎo)致死鎖你知道嗎
死鎖從文字理論上說(shuō)明的是兩個(gè)線程,可以認(rèn)為是兩個(gè)人A和B,A在等待B完成某件事情,B又在等待A完成某件事情。

那如果在代碼中,單線程的某個(gè)函數(shù),有沒(méi)有可能導(dǎo)致死鎖呢?
我們看下面的代碼
#include<pthread.h>
#include<string.h>
#include<errno.h>
#include<stdio.h>
#include<unistd.h>
pthread_mutex_t mutex;
int main()
{
pthread_mutex_init(&mutex,NULL);
printf("mutex init\n");
pthread_mutex_lock(&mutex);
printf("mutex lock#1\n");
pthread_mutex_lock(&mutex);
printf("mutex lock#2\n");
pthread_mutex_unlock(&mutex);
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);
return 0;
}你看這樣的代碼會(huì)不會(huì)導(dǎo)致死鎖呢?
線程在上鎖后,又馬上繼續(xù)嘗試上鎖,這樣的情況會(huì)不會(huì)存在?
類似這樣的代碼
int test_function(void)
{
//lock
do_something()
if(x) return -1
//unlock
}在上鎖后,然后下面會(huì)因?yàn)槟撤N判斷后退出,下一次進(jìn)來(lái)后,又會(huì)進(jìn)行上鎖,這樣的死鎖是因?yàn)榇a邏輯不正確導(dǎo)致的,也是很多新手常犯的問(wèn)題。
如果是兩個(gè)線程死鎖的情況呢?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t g_mutex_lock;
pthread_mutex_t g_mutex_lock2;
void *func1(void* args)
{
printf("%s(),LINE=%d\n",__FUNCTION__,__LINE__);
pthread_mutex_lock(&g_mutex_lock);
sleep(1);
pthread_mutex_lock(&g_mutex_lock2);
printf("%s(),LINE=%d\n",__FUNCTION__,__LINE__);
pthread_mutex_unlock(&g_mutex_lock);
pthread_mutex_unlock(&g_mutex_lock2);
return NULL;
}
void *func2(void* args)
{
printf("%s(),LINE=%d\n",__FUNCTION__,__LINE__);
pthread_mutex_lock(&g_mutex_lock2);
sleep(1);
pthread_mutex_lock(&g_mutex_lock);
printf("%s(),LINE=%d\n",__FUNCTION__,__LINE__);
pthread_mutex_unlock(&g_mutex_lock2);
return NULL;
}
int main(void)
{
int ret;
pthread_t thread_1;
pthread_t thread_2;
printf("%s(),LINE=%d\n",__FUNCTION__,__LINE__);
ret = pthread_mutex_init(&g_mutex_lock, NULL);
if (ret != 0) {
printf("mutex init failed\n");
return -1;
}
ret = pthread_mutex_init(&g_mutex_lock2, NULL);
if (ret != 0) {
printf("mutex2 init failed\n");
return -1;
}
pthread_create(&thread_1, NULL, func1, NULL);
pthread_create(&thread_2, NULL, func2, NULL);
pthread_join(thread_1, NULL);
pthread_join(thread_2, NULL);
pthread_mutex_destroy(&g_mutex_lock);
pthread_mutex_destroy(&g_mutex_lock2);
printf("%s(),LINE=%d\n",__FUNCTION__,__LINE__);
return 0;
}上面的代碼比較典型了
線程1拿到1號(hào)鎖后,開(kāi)始等待2號(hào)鎖,線程2拿到2號(hào)鎖后,就開(kāi)始等待一號(hào)鎖。他們屬于互相等待的情況。
代碼輸出
linux@ubuntu:/study$ gcc argc.c -pthread && ./a.out
main(),LINE=37
func1(),LINE=11
func2(),LINE=23
最后,線程出現(xiàn)死鎖不會(huì)正常情況不會(huì)導(dǎo)致crash,除非代碼上因?yàn)榧渔i存在的一些空指針。
所以單線程也是有可能導(dǎo)致死鎖的。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Vscode中接入Deepseek的實(shí)現(xiàn)
本文主要介紹了Vscode中接入Deepseek的實(shí)現(xiàn),包括登錄Deepseek官網(wǎng)、申請(qǐng)APIKEY、安裝和配置VSCode插件,具有一定的參考價(jià)值,感興趣的可以了解一下2025-02-02
關(guān)于C++多重繼承下虛表結(jié)構(gòu)的問(wèn)題
這篇文章主要介紹了C++ 多重繼承下虛表結(jié)構(gòu)的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
C語(yǔ)言通過(guò)三種方法實(shí)現(xiàn)屬于你的通訊錄
本文將實(shí)現(xiàn)一個(gè)通訊錄,來(lái)實(shí)現(xiàn)人員的增刪插改功能。文中通過(guò)三種形式來(lái)實(shí)現(xiàn)用戶的增刪插改,其實(shí)也就是一點(diǎn)點(diǎn)的優(yōu)化版本,從靜態(tài)的實(shí)現(xiàn),到動(dòng)態(tài)的實(shí)現(xiàn),最后以文件的形式來(lái)完成,請(qǐng)大家和我一起往下看吧2022-11-11
C++實(shí)現(xiàn)N個(gè)骰子的點(diǎn)數(shù)算法
這篇文章主要介紹了C++實(shí)現(xiàn)N個(gè)骰子的點(diǎn)數(shù)算法,用兩種方法實(shí)現(xiàn)了該功能,是非常實(shí)用的技巧,需要的朋友可以參考下2014-09-09
C++超詳細(xì)實(shí)現(xiàn)二叉樹(shù)的遍歷
本章將會(huì)詳細(xì)講解二叉樹(shù)遍歷的四種方式,分別為前序遍歷、中序遍歷、后續(xù)遍歷和層序遍歷。在學(xué)習(xí)遍歷之前,會(huì)先帶大家回顧一下二叉樹(shù)的基本概念2022-05-05
Qt自定義表頭實(shí)現(xiàn)過(guò)濾功能的方法
這篇文章主要個(gè)給大家介紹了關(guān)于Qt自定義表頭實(shí)現(xiàn)過(guò)濾功能的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Qt具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
C++實(shí)現(xiàn)順序表的常用操作(插入刪出查找輸出)
實(shí)現(xiàn)順序表的插入,刪除,查找,輸出操作在C語(yǔ)言中經(jīng)常用到。下面小編給大家整理實(shí)現(xiàn)代碼,一起看下吧2016-08-08

