線程基礎/線程同步和互斥

學習筆記,小白可以相互學習,大佬看到能告訴咱理解不對的地方就好了。


1.線程基礎

   爲了提高系統的性能,許多操作系統規範裏引入了輕量級進程的概念,也被稱爲線程。

在同一個進程中創建的線程共享該進程的地址空間。

Linux裏同樣用task_struct來描述一個線程。線程和進程都參與統一的調度。

通常線程指的是共享相同地址空間的多個任務。

使用多線程的好處:大大提高了任務切換的效率。避免了額外的TLB&cache的刷新。

編譯時要加庫文件-lpthread


一個進程中的多個線程共享以下資源
可執行的指令
靜態數據
進程中打開的文件描述符
信號處理函數
當前工作目錄
用戶ID
用戶組ID

每個線程私有的資源如下
線程ID(TID)
PC(程序計數器)和相關寄存器
堆棧(局部變量,返回地址)
錯誤號(errno)
信號掩碼和優先級
執行狀態和屬性

NPTL線程庫中提供瞭如下基本操作
創建線程
刪除線程
控制線程

return 返回函數
exit 退出進程
pthread_exit 線程的退出


函數


線程創建
頭文件 #include<pthread.h>
原型 int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*routine)(viod *),void *arg)
參數 thread:創建的線程
  attr:指定線程的屬性,NULL表示缺省屬性
  routine:線程執行的函數
  arg:傳遞給線程執行的函數的參數
返回值 成功:0
  出錯:返回錯誤號

#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>

pthread_t thread;

void *thread_func(void * arg)
{
    printf("arg:%s\n",(char *)arg);
    while(1)
    {
        sleep(1);
        printf("nihao\n");
    }
}


int main()
{
    char buf[] = "hello world";
    if( 0 != pthread_create(&thread,NULL,thread_func,buf))
    {
        perror("pthread_create");
        exit(-1);
    }
    while(1)
    {
        sleep(1);
        printf("hello world \n");
    }
    return 0;
}



等待線程結束
頭文件 #include<prhread.h>
原型 int pthread_join(pthread_t thread,void **value_ptr)
參數 thread:要等待的線程
value_ptr:指針*value_ptr指向的線程返回的參數
返回值 成功:0
出錯:返回錯誤號

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>

pthread_t thread;

void *thread_func(void *arg)
{
	int i;
	for (i = 0; i < 5; i++) {
		sleep(1);
		printf("arg: %s\n", (char *)arg);
	}

	pthread_exit("thread exit!");
}

int main()
{
	if (0 != pthread_create(&thread, NULL, thread_func, "hello world")) {
		perror("pthread_create");
		exit(-1);
	}

	printf("pthread_create success!\n");

	void *ptr = NULL;
	if (0 != pthread_join(thread, &ptr)) {
		perror("pthread_join");
		exit(-1);
	}

	printf("ptr: %s\n", (char *)ptr);

	return 0;
}

線程退出
頭文件 #include<pthread.h>
原型 void pthread_exit(void *value_ptr)
參數 value_ptr:線程退出時返回的值

取消線程
頭文件 #include<pthread.h>
原型 int pthread_cancel(pthread_t thread)
參數 thread:要取消的線程
返回值 成功:0
出錯:返回錯誤號

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>

pthread_t thread;

void *thread_func(void *arg)
{
	int i;
	for (i = 0; i < 5; i++) {
		sleep(1);
		printf("arg: %s\n", (char *)arg);
	}

	pthread_exit("thread exit!");
}

int main()
{
	if (0 != pthread_create(&thread, NULL, thread_func, "hello world")) {
		perror("pthread_create");
		exit(-1);
	}

	printf("pthread_create success!\n");

	sleep(2);
	if (0 != pthread_cancel(thread)) {
		perror("pthread_cancel");

		void *ptr = NULL;
		if (0 != pthread_join(thread, &ptr)) {
			perror("pthread_join");
			exit(-1);
		}

		printf("ptr: %s\n", (char *)ptr);
	}else 
		printf("thread canceled\n");

	return 0;
}



2.線程同步和互斥

2.1線程間機制

多線程共享一個進程的地址空間

優點:線程間很容易進行通信

缺點:多個線程同時訪問共享對象時需要引入同步和互斥機制


2.2線程間同步

同步指的是多個任務(線程)按照約定的順序相互配合完成一件事情。

1968年,Edsgar Dijkstra基於信號量的概念提出了一種同步機制。

由信號量來決定線程是否繼續運行還是阻塞等待。

    

   2.3P/V操作

信號量代表某一類資源,其值表示系統中該資源的數量。

信號量是一個受保護的變量,只能通過三種操作來訪問

1.初始化(設定變量開始資源的數量)
2.P操作(申請資源,同時資源數目減一)
3.V操作(釋放資源,同時資源數目加一)

     信號量的值是爲非負整數

(二值信號量:值只有0和1,0表示資源不可用,1可用)

 (計數信號量:表示有多少塊資源)


   P(S)含義如下:

if(信號量的值大於0)

{

申請資源的任務繼續運行;信號量的值減一;

}

else

{

申請資源的任務阻塞;

}

 V(S)含義如下:

if(沒有任務等待該資源)

{

信號量的值加一;

}

else

{

喚醒第一個等待的任務,讓其繼續運行;

}



函數

初始化信號量
頭文件 #include<semaphore.h>
原型 int sem_init(sem_t *sem,int pshared,unsigned int value)
參數 sem:初始化的信號量
pshared:信號量的共享範圍
(0:線程間使用,非0:進程間使用)
value:信號量的初值(非負整數)
返回值 成功:0
出錯:-1

P操作(申請資源)
頭文件 #include<semaphore.h>
原型 int  sem_wait(sem_t *sem)
參數 sem;信號量
返回值 成功:0
出錯:-1


V操作(釋放資源)
頭文件 #include<semaphore.h>
原型 int  sem_post(sem_t *sem)
參數 sem;信號量
返回值 成功:0
出錯:-1

2.4線程間互斥

引入互斥鎖的目的是用來保證共享資源的完整性

互斥鎖主要用來保護臨界資源

每個臨界資源都由一個互斥鎖來保護,任何時刻最多只能有一個線程能訪問該資源(線程不能同時執行)


函數

初始化互斥鎖
頭文件 #include<pthread.h>
原型 int pthread_mutex_init(pthread_mutex_t *mutex,pthread_mutexattr_ *attr)
參數 mutex:互斥鎖
attr:互斥鎖屬性//NULL表示缺省屬性
返回值 成功:0
出錯:-1


申請互斥鎖
頭文件 #include<pthread.h>
原型 int pthread_mutex_lock(pthread_mutex_t *mutex)
參數 mutex:互斥鎖
返回值 成功:0
出錯:返回錯誤號


釋放互斥鎖
頭文件 #include<pthread.h>
原型 int pthread_mutex_unlock(pthread_mutex_t *mutex)
參數 mutex:互斥鎖
返回值 成功:0
出錯:返回錯誤號

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>

#include <pthread.h>
#include <semaphore.h>

pthread_t thread;
sem_t sem_w, sem_r;

char buf[100];

void *thread_func(void *arg)   //讀
{
	while (1) {
		sem_wait(&sem_r);
		fputs(buf, stdout);
		sem_post(&sem_w);
	}
}

int main()
{
	if (0 != sem_init(&sem_w, 0, 1)) {
		perror("sem_init sem_w");
		exit(-1);
	}
	if (0 != sem_init(&sem_r, 0, 0)) {
		perror("sem_init sem_r");
		exit(-1);
	}

	if (0 != pthread_create(&thread, NULL, thread_func, NULL)) {
		perror("pthread_create");
		exit(-1);
	}

	while (1) {  //寫
		sem_wait(&sem_w);
		fgets(buf, sizeof(buf), stdin);
		sem_post(&sem_r);
	}

	return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>

int count = 0;
int value1, value2;

pthread_t thread;
pthread_mutex_t mutex;

void *thread_func(void *arg)
{
	while (1) {
		pthread_mutex_lock(&mutex);
		if (value1 != value2)
			printf("%d, %d\n", value1, value2);
		pthread_mutex_unlock(&mutex);
	}
}

int main()
{
	if (0 != pthread_mutex_init(&mutex, NULL)) {
		perror("pthread_mutex_init");
		exit(-1);
	}
	
	if (0 != pthread_create(&thread, NULL, thread_func, NULL)) {
		perror("pthread_create");
		exit(-1);
	}

	while (1) {
		count++;
		pthread_mutex_lock(&mutex);  //加鎖
		value1 = count;
		value2 = count;
		pthread_mutex_unlock(&mutex); //解鎖
	}
}

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<unistd.h>


//設計一個多線程程序,實現一個整型數組
//一個線程,正序打印
//另外一個線程,倒序打印

pthread_t thread;
sem_t sem_w;
sem_t sem_r;
pthread_mutex_t mutex;
int buf[10] = {};


void *thread_func(void *arg)//正序打印
{

    int j;
    while(1)
    {
        sem_wait(&sem_w);
        for(j = 0; j < 10; j++)
        {
            scanf("%d,",&buf[9-j]);
        }
        for(j = 0; j < 10; j++)
        {
            printf("%d",buf[9-j]);
        }
        printf("\n");
        sem_post(&sem_r);
    }
}

int main()
{
    if( 0 != sem_init(&sem_w,0,1))
    {
        perror("sem_init sem_w");
        exit(-1);
    }
    if( 0 != sem_init(&sem_r,0,0))
    {
        perror("sem_init sem_r");
        exit(-1);
    }
    if( 0 != pthread_create(&thread,NULL,thread_func,NULL))
    {
        perror("pthread_create");
        exit(-1);
    }

//倒序打印

    int j;
    while(1)
    {
        sem_wait(&sem_r);
        for(j = 0; j < 10;j++)
        {
            printf("%d--",buf[j]);   
        }
        printf("\n");
        sem_post(&sem_w);
        sleep(1);
    }
    printf("\n");

}

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
//設計一個多線程程序,實現一個整型數組
//一個線程,往數組裏面存放數據
//另外一個線程,讀取數組裏面的內容

pthread_t thread;
pthread_t thread1;
sem_t sem_w;
sem_t sem_r;
int buf[10] = {0};

void *thread_func(void *arg)//寫
{

    sem_wait(&sem_w);
    int j;
    for(j = 0; j < 10; j++)
    {
        scanf("%d,",&buf[j]);
    }
    sem_post(&sem_r);
}

void *thread_func1(void *arg)//讀
{

    sem_wait(&sem_r);
    int i;
    for(i = 0; i < 10; i++)//讀
    {
        fprintf(stdout,"%d-",buf[i]);
    }
    sem_post(&sem_w);
    printf("\n");
}

int main()
{
    if( 0 != sem_init(&sem_w,0,1))
    {
        perror("sem_init sem_w");
        exit(-1);
    }
    if( 0 != sem_init(&sem_r,0,0))
    {
        perror("sem_init sem_r");
        exit(-1);
    }
    if( 0 != pthread_create(&thread,NULL,thread_func,NULL))
    {
        perror("pthread_create");
        exit(-1);
    }

    if( 0 != pthread_create(&thread1,NULL,thread_func1,NULL))
    {
        perror("pthread_create");
        exit(-1);
    }

    void *ptr = NULL;
    if( 0!= pthread_join(thread,&ptr))
    {
        perror("pthread_join");
        exit(-1);
    }
    void *ptr1 = NULL;
    if( 0!= pthread_join(thread1,&ptr1))
    {
        perror("pthread_join1");
        exit(-1);
    }

    
    //pthread_join(thread,NULL);//等待線程結束
    //pthread_join(thread1,NULL);

}



#include<stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t mutex;

pthread_t thread;
void *buf = NULL;

void reserve(int *buf,int len)
{
    int i = 0;
    int j = 0;
    j = len -1;
    int k = 0;

    pthread_mutex_lock(&mutex);
    for(i = 0;i < len/2;i ++)
    {
        buf[i] ^= buf[j];
        buf[j] ^= buf[i];
        buf[i] ^= buf[j];
        j--;
    }

    for(k = 0; k < 10; k++)
    {
        printf("%2d",buf[k]);
        fflush(stdout);
    }
    printf("\n");
    pthread_mutex_unlock(&mutex);

}
void * thread_fun(void *arg)
{
    int *p = arg;
    reserve(p,10);
    pthread_exit("success");
}

int main()
{
    int a[10] = {1,2,3,4,5,6,7,8,9,0};
    int j = 0;
    if(0 != pthread_mutex_init(&mutex,NULL))
    {
        printf("pthread_mutex_init is falil\n");
        exit(-1);
    }
    else
    {
        //創建線程
        if(0 != pthread_create(&thread,NULL,thread_fun,a))
        {
            perror("pthread_create");
            exit(-1);
        }
        else
        {
            pthread_mutex_lock(&mutex);
            for(j = 0; j < 10; j ++)
            {
                printf("%d\n",a[j]);
            }
            pthread_mutex_unlock(&mutex);
            pthread_join(thread,&buf);
            printf("%s\n",(char *)buf);
        }
    }
    return 0;
}


發佈了31 篇原創文章 · 獲贊 21 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章