【編程練習】多線程編寫一個存在死鎖的代碼

昨天的面試被這個問題掛了,平時忽略了這方面的學習,這裏補一下這裏的知識。
多線程的基礎這篇裏有講:https://blog.csdn.net/weixin_44611644/article/details/95453398
或者參考c++多線程|菜鳥教程 直接搜得到。

下面給出我的c++簡單代碼。變量x1,x2代表2個資源,值爲1時相當於可以訪問,值爲0時代表被某一線程鎖住,其他線程不能訪問。

#include <iostream>
#include <pthread.h>//線程頭文件 
using namespace std;
int x1=1;//1表示可以訪問 
int x2=1;

// 線程的運行函數
void* fun1(void* args)
{
	bool res=true;//記錄線程是否訪問成功 
    cout << "線程1創建成功" << endl;
    if(x1==1)
	{	
		x1=0;//訪問x1,給x1加鎖
		cout << "線程1訪問變量x1,給x1加鎖" << endl;
	}
	else
	{
		res=false;
		cout<<"線程1訪問變量x1失敗,x1被其他線程加鎖"<<endl;
	}
	if(x2==1)
	{	
		x2=0;//訪問x2,給x2加鎖 
		cout << "線程1訪問變量x2,給x2加鎖" << endl;
	}
	else
	{
		res=false;
		cout<<"線程1訪問變量x2失敗,x2被其他線程加鎖"<<endl;
	}
	if(res)
	{
		x1=1;
		x2=1;//給x1 x2解鎖 
		cout << "線程1訪問結束 x1,x2解鎖" << endl;
	}
	else
	{
		cout<<"線程1被阻塞訪問無法完成"<<endl;
	}
	return 0;
}

void* fun2(void* args)
{
	bool res=true;//記錄線程是否訪問成功 
    cout << "線程2創建成功" << endl;
    if(x2==1)
	{	
		x2=0;//訪問x2,給x2加鎖 
		cout << "線程2訪問變量x2,給x2加鎖" << endl;
	}
	else
	{
		res=false;
		cout<<"線程2訪問變量x2失敗,x2被其他線程加鎖"<<endl;
	}
	if(x1==1)
	{	
		x1=0;//訪問x1,給x1加鎖	
		cout << "線程2訪問變量x1,給x1加鎖" << endl;
	}
	else
	{
		res=false;
		cout<<"線程2訪問變量x1失敗,x1被其他線程加鎖"<<endl;
	}
	if(res)
	{
		x2=1;
		x1=1;//給x1 x2解鎖 
		cout << "線程2訪問結束 x1,x2解鎖" << endl;
	}
	else
	{
		cout<<"線程2被阻塞,訪問無法完成"<<endl;
	}
	return 0;
}

int main()
{
    // 定義線程的 id 變量,多個變量使用數組
    pthread_t tids[2];
    //參數依次是:創建的線程id,線程參數,調用的函數,傳入的函數參數
    int ret1 = pthread_create(&tids[0], NULL, fun1, NULL);
    int ret2 = pthread_create(&tids[1], NULL, fun2, NULL);
    if (ret1 != 0)
    {
           cout << "pthread_create error: error_code=" << ret1 << endl;
    }
    if (ret2 != 0)
    {
           cout << "pthread_create error: error_code=" << ret2 << endl;
    }
    //等各個線程退出後,進程才結束,否則進程強制結束了,線程可能還沒反應過來;
    pthread_exit(NULL);
    return 0; 
}

在這裏插入圖片描述
運行時結果如上,由於線程1把x1加鎖,線程2把x2加鎖。線程1訪問x2時不能進行,線程2訪問x1時不能進行,他們發生了互鎖。這是因爲出現了死鎖的情況之 “請求和保持”,在請求別的資源時還持有自己的資源不釋放,容易造成這種互鎖現象。在使用種還可以把線程內部的訪問設置成循環,如果獲取到全部資源才退出,否則就一直循環請求資源。這樣的話死鎖程序就停不下來,一直重複顯示xx無法訪問 線程無法完成。

這裏的換行符出現的不規律,我猜測的原因是cout<<endl重新刷新緩衝區導致的不同步,歡迎指正。

解決辦法是,把<<endl去掉,換成在輸出內容末尾加上\n。結果如下
在這裏插入圖片描述
在C++11中還加入了thread線程類,和stl的容器使用方法相似。
我使用的Devc是默認不使用c++11的,使時會報錯,我們需要在編譯器選項裏修改
在這裏插入圖片描述
一個簡潔的線程創建如下
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章