Loading... # 线程 线程依附于进程,进程中可以共享数据 | 文件描述符 | | - | | 全局变量 | | 用户ID组ID | | 工作目录 | | 同处于4G内存空间 | | | 但有些资源每个线程各有一份 | 线程ID | | - | | 上下文、包括寄存器值,程序计数器和栈指针。 | | 栈空间 | | errno变量 | | 信号屏蔽字 | | 调度优先级 | 线程库由POSIX标准定义的,被称为POSIX thread 或 pthread,Linux上函数位于libphread共享库中。 ## 线程API 用的时候最好查下百度这里用作记录 **对于单线程的进程,内核中tid==pid,对于多线程进程,他们有相同的pid,不同的tid。tid用于描述内核真实的pid和tid信息。** **pthread_self返回的是posix定义的线程ID,man手册明确说明了和内核线程tid不同。它只是用来区分某个进程中不同的线程,当一个线程退出后,新创建的线程可以复用原来的id。** | 函数 | 说明 | | | - | - | - | | pthread_create | 线程创建 | 线程有两种状态 joinable(自己结束exit都不会释放堆栈)-unjoinable(自己结束之后释放堆栈) | | pthread_self | 获取当前线程ID | \%lf | | pthread_exit | 退出当前线程 | | | pthread_cancel | 发送终止信号 | 使子进程原地爆炸 | | pthread_join | 等待线程结束 | | | pthread_detach | 等线程结束销毁 | 将线程状态更改为unjoinable | | gettid | 获取内核进程PID | \%d | ## 线程代码 ``` #include <stdio.h> #include <pthread.h> #include <unistd.h> // int g_source = 0; pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER; void *workthread1() { for(int i=0;i<100000000000;i++) { g_source++; printf("thread1:[%ld]--pid=[%d]\n",pthread_self(),getpid()); } return 0; } int main() { //创建线程 pthread_t pthread; pthread_create(&pthread,NULL,workthread1,0); //发送终止线程信号。 pthread_cancel(pthread); //更改线程状态为unjoinable 线程结束就自己释放 //pthread_detach(pthread); for(int i =0;i<10;i++) { printf("main:[%d]pid=[%d]\n",i,getpid()); }; pthread_join(pthread,NULL); return 0; } ``` # 线程同步 ## 互斥体 | 函数 | 说明 | | - | - | | pthread_mutex_destroy | 销毁互斥体 | | pthread_mutex_init | 初始化互斥体 | | pthread_mutex_lock | 获取锁 | | pthread_mutex_trylock | 尝试获取锁,不阻塞,先返回EBUSY | | pthread_mutex_unlock | 释放锁 | <span style="color:Crimson ">注意: 如果一个线程调用两次lock获取锁,在第二次调用时,由于锁已经被占用,该线程会挂起等待别的线程释放锁,然而锁正在被自己占用,该线程又被挂起,因此就会永久等待,(死锁); 线程A获取了锁1,线程B获取了锁2,如果线程A调用lock试图获取锁2 ,因为锁2被占用结果挂起等待锁2结束,而锁二也试图获取锁1,因为锁1被挂起,无法释放,锁2也没机会获取了,造成了死锁</span> <span style="color:Crimson ">信号量没有线程拥有者概念,在线程运行的时候,其他线程可以直接释放该锁</span> ## 代码 ``` #include <stdio.h> #include <pthread.h> #include <unistd.h> //全局变量 int g_source = 0; //全局锁 pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER; void *workthread1() { for(int i=0;i<1000000;i++) { //首先上锁 pthread_mutex_lock(&counter_mutex); //对全局变量进行++ g_source++; //解锁 pthread_mutex_unlock(&counter_mutex); } pthread_detach(pthread_self()); return 0; } void *workthread2() { for(int i=0;i<1000000;i++) { pthread_mutex_lock(&counter_mutex); g_source++; pthread_mutex_unlock(&counter_mutex); } pthread_detach(pthread_self()); return 0; } int main() { pthread_t pthread[2]; pthread_create(&pthread[0],NULL,workthread1,0); pthread_create(&pthread[1],NULL,workthread2,0); for(int i =0;i<2;i++) { pthread_join(pthread[i],NULL); }; printf("%d\n",g_source); return 0; } ``` ## 信号量 mutex 变量非0及1,可看作一种资源数量,初始化Mutex为1,表示有一个可以用的资源,加锁获取资源mutex减到0,不可用,解锁时释放资源,mutex重新加1。 <span style="color:Crimson ">信号量没有线程拥有者概念,在线程运行的时候,其他线程可以直接释放该锁</span> | 函数 | 说明 | | - | - | | sem_init | 初始化信号量 | | sem_wait | 获取信号量,获取成功后信号数-1 | | sem_trywait | 获取信号量,不阻塞 与sem_waite功能一样 | | sem_post | 释放一个信号量,信号数+1 | | sem_destroy | 销毁信号量 | ## 代码 ``` #include <stdio.h> #include <pthread.h> #include <unistd.h> #include <semaphore.h> // int g_source = 0; //创建全局信号量 sem_t g_semaphore; void *workthread1() { for(int i=0;i<1000000;i++) { sem_wait(&g_semaphore); //等待闲置信号量 g_source++; sem_post(&g_semaphore); //信号量释放 } pthread_detach(pthread_self()); return 0; } void *workthread2() { for(int i=0;i<1000000;i++) { sem_wait(&g_semaphore);//等待闲置信号量 g_source++; sem_post(&g_semaphore);//信号量释放 } pthread_detach(pthread_self()); return 0; } int main() { sem_init(&g_semaphore,0,1); pthread_t pthread[2]; // pthread_create(&pthread[0],NULL,workthread1,0); pthread_create(&pthread[1],NULL,workthread2,0); for(int i =0;i<2;i++) { pthread_join(pthread[i],NULL); }; printf("%d\n",g_source); sem_destroy(&g_semaphore); return 0; } ``` 最后修改:2021 年 03 月 03 日 © 允许规范转载 赞 0 如果觉得我的文章对你有用,请随意赞赏