學習筆記,小白可以相互學習,大佬看到能告訴咱理解不對的地方就好了。
1.線程基礎
爲了提高系統的性能,許多操作系統規範裏引入了輕量級進程的概念,也被稱爲線程。
在同一個進程中創建的線程共享該進程的地址空間。
Linux裏同樣用task_struct來描述一個線程。線程和進程都參與統一的調度。
通常線程指的是共享相同地址空間的多個任務。
使用多線程的好處:大大提高了任務切換的效率。避免了額外的TLB&cache的刷新。
編譯時要加庫文件-lpthread
可執行的指令 |
靜態數據 |
進程中打開的文件描述符 |
信號處理函數 |
當前工作目錄 |
用戶ID |
用戶組ID |
線程ID(TID) |
PC(程序計數器)和相關寄存器 |
堆棧(局部變量,返回地址) |
錯誤號(errno) |
信號掩碼和優先級 |
執行狀態和屬性 |
創建線程 |
刪除線程 |
控制線程 |
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 |
頭文件 | #include<semaphore.h> |
原型 | int sem_wait(sem_t *sem) |
參數 | sem;信號量 |
返回值 | 成功:0 出錯:-1 |
頭文件 | #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;
}