操作系统:Linux 多线程编程
原载 来源
@[toc]
线程创建
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
```C #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <unistd.h> void myThread1(void data) { int i = 0; int num = (int)data; for (i = 0; i < 20; i++) { printf("thread1 : %d", num); sleep(1); } return (void)0; }
void myThread2(void) { int i = 0; int num = (int)data; for (i = 0; i < 20; i++) { printf("thread2 : %d", num); sleep(1); } return (void)0; } //线程创建 int threadcreate(pthreadt thid, const pthreadattrt attr, void (callback)(void arg), void* data) { int ret = 0; ret = pthreadcreate(th_id, attr, callback, data); if (ret) { printf("thread create failes"); return 1; } return 0; }
int main(void) { int i = 0, ret = 0; pthreadt id1, id2; int test = 666, test2 = 888; int attr1 = &test, attr2 = &test2; /创建线程1/ ret = threadcreate(&id1, NULL, myThread1, (void)attr1); /创建线程2/ ret = thread_create(&id2, NULL, myThread2, (void)attr1);
sleep(10); return 0; }
结果:
![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RZDs1nS5-1683167031368)(en-resource://database/728:1)\]](https://i-blog.csdnimg.cn/blog_migrate/341ca1a593b5f431d91716aaf1ae1c40.png)
### 线程终止
> `void pthread_exit(void *retval);`
使用函数退出是线程的主动行为:由于一个进程当中线程共享资源,因此通常在线程退出之后,退出线程所占资源并不会随着线程的退出而释放。可以使用pthread_join()函数来同步和释放资源。
### 等待线程终止
> `int pthread_join(thread_t tid, void **status);`
- 线程自己运行结束,或者调用pthread_exit()结束,线程都会释放自己独有的空间资源。
- 如果线程是非分离的,线程会保留线程ID号,直到其他线程通过“joining”这个线程确认其已死亡。join的结果是joing线程得到已终止线程的退出状态。已终止的线程将消失。
- 如果线程是分离的,不需要使用thread_exit(),线程自己运行结束,就会释放所有资源。
- **子线程一定要使用pthread_join()或者设置为分离状态来结束线程,否则线程的资源不会被完全释放。**
### 线程属性初始化
> //线程属性初始化
> `int pthread_attr_init(pthread_attr_t *attr);`
> //线程属性去除初始化
> `int pthread_attr_destroy(pthread_attr_t *attr);`
### 线程分离
> //修改线程的分离状态属性
> `int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);`
> //获取线程的分离状态属性
> `int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);`
- 在任何一个时间点上,线程都是可结合或者分离的。一个可结合的线程能够被其他线程回收其资源和杀死,在被其他线程回收之前,他的存储器资源不会释放;相反,一个分离的线程是不能被其他线程回收或者杀死的,他的存储器资源在程序结束时自动释放。
### 线程的继承性/调度策略/调度参数
> //设置线程的继承性
> `int pthread_attr_setinheritsched(pthread_attr_t *attr,`
> //获取线程的继承性
> `int pthread_attr_getinheritsched(const pthread_attr_t *attr,int *inheritsched);`
> //设置线程的调度策略
> `int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);`
> //获取线程的调度策略
> `int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);`
> //设置线程的调度参数
> `int pthread_attr_setschedparam(pthread_attr_t *attr,const struct sched_param *param);`
> //获取线程的调度参数
> `int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);`
#include <pthread.h> #include <sched.h> #include <stdio.h>
void checkHeritsched(int policy) { if (PTHREADEXPLICITSCHED == policy) { printf("the heritsched is PTHREADEXPLICITSCHED\n"); } if (PTHREADINHERITSCHED == policy) { printf("the heritsched is PTHREADEXPLICITSCHED\n"); } }
void checkSchedpolicy(int policy) { if (SCHEDFIFO == policy) { printf("the schedpolicy is SCHEDFIFO\n"); } if (SCHEDRR == policy) { printf("the schedpolicy is SCHEDRR\n"); } if (SCHEDOTHER == policy) { printf("the schedpolicy is SCHEDOTHER\n"); } }
void childthread(void arg) { int policy = 0; int maxpriority = 99, minpriority = 1; struct schedparam param; pthreadattrt attr;
/初始化线程属性/ pthreadattrinit(&attr);
/设置线程继承性/ pthreadattrsetinheritsched(&attr, PTHREADEXPLICITSCHED); /获取线程继承性/ pthreadattrgetinheritsched(&attr, &policy); checkHeritsched(policy);
//获取线程调度策略 pthreadattrgetschedpolicy(&attr, &policy); checkSchedpolicy(policy); //设置线程调度策略 pthreadattrsetschedpolicy(&attr, SCHEDRR); //获取线程调度策略 pthreadattr_getschedpolicy(&attr, &policy); checkSchedpolicy(policy);
//获得系统支持的线程优先级最大值 schedgetprioritymax(maxpriority); //获得系统支持的线程优先级最小值 schedgetprioritymin(minpriority); printf("Max priority:%u\n", maxpriority); printf("Min priority:%u\n", minpriority); param.schedpriority = maxpriority;
//设置线程的调度参数 pthreadattrsetschedparam(&attr, ¶m); //获得线程的调度参数 printf("schedpriority: %u\n", param.schedpriority);
//恢复线程属性 pthreadattrdestroy(&attr); }
int main() { pthreadt thid; pthreadcreate(&thid, NULL, childthread, NULL); pthreadjoin(th_id, NULL); return 0; }
结果:
![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wAHhdtGq-1683167031369)(en-resource://database/730:1)\]](https://i-blog.csdnimg.cn/blog_migrate/15eb705b45774331519eb9691778ec93.png)
### 互斥锁使用实例
#include <stdio.h> #include <pthread.h> #include "thread_test.h"
/*
//互斥锁初始化
int pthreadmutexinit(pthreadmutext mutex, const pthreadmutexattrt mutexattr);
//上锁
int pthreadmutexlock(pthreadmutext* mutex);
//尝试上锁,若已锁直接报错不等待
int pthreadmutextrylock(pthreadmutext* mutex);
//解锁
int pthreadmutexunlock(pthreadmutext* mutex);
//销毁锁
int pthreadmutexdestroy(pthreadmutext* mutex);
*/
void mutexmyThread1(void msg); void mutexmyThread2(void msg);
int gvalue = 0; pthreadmutex_t mutex;
int main(int argc, char argv[]) { pthreadt th1, th2; if (0 != pthreadmutexinit(&mutex, NULL)) { printf("mutexinit error\n"); exit(1); } threadcreate(&th1, NULL, (void)(mutexmyThread1), NULL); threadcreate(&th2, NULL, (void*)mutexmyThread2, NULL); sleep(1); printf("end gvalues is %d\n", gvalue); //创建了锁就要记得销毁锁。 pthreadmutexdestroy(&mutex); return 0; }
int mutexlock(pthreadmutext* mutex) { int val; val = pthreadmutex_lock(mutex); if (0 != val) { printf("lock error\n"); } return val; }
void mutexmyThread1(void* msg) { mutexlock(&mutex); gvalue = 0; printf("now gvalue is %d\n", gvalue); gvalue += 5; printf("add 5 now gvalue is %d\n", gvalue); pthreadmutexunlock(&mutex); printf("thread1 unlock\n"); }
void mutexmyThread2(void* msg) { mutexlock(&mutex); gvalue = 0; printf("now gvalue is %d\n", gvalue); gvalue += 2; printf("add 2 now gvalue is %d\n", gvalue); pthreadmutexunlock(&mutex); printf("thread2 unlock\n");
}
结果:

#include <stdio.h> #include <pthread.h> #include "thread_test.h"
void mutexmyThread1(void msg); void mutexmyThread2(void msg);
int gvalue = 1; pthreadmutex_t mutex;
#ifdef MUTEX int main(int argc, char argv[]) { pthreadt th1, th2; if (0 != pthreadmutexinit(&mutex, NULL)) { printf("mutexinit error\n"); exit(1); } threadcreate(&th1, NULL, (void)mutexmyThread1, NULL); threadcreate(&th2, NULL, (void*)mutexmyThread2, NULL); sleep(1); printf("end gvalues is %d\n", gvalue); //创建了锁就要记得销毁锁。 pthreadmutexdestroy(&mutex);
return 0; } #endif //MUTEX
int mutexlock(pthreadmutext* mutex) { int val = 0; val = pthreadmutex_lock(mutex); if (0 != val) { printf("lock error\n"); } return val; }
int mutextrylock(pthreadmutext* mutex) { int val = 0; val = pthreadmutex_trylock(mutex); if (0 != val) { printf("the mutex is locked\n"); } else { printf("trylock success\n"); } return val; }
void mutexmyThread1(void* msg) { mutexlock(&mutex); gvalue = 0; printf("now gvalue is %d\n", gvalue); gvalue += 5; printf("add 5 now gvalue is %d\n", gvalue); pthreadmutexunlock(&mutex); printf("thread1 unlock\n"); }
void mutexmyThread2(void* msg) { mutextrylock(&mutex); gvalue = 0; printf("now gvalue is %d\n", gvalue); gvalue += 2; printf("add 2 now gvalue is %d\n", gvalue); pthreadmutexunlock(&mutex); printf("thread2 unlock\n");
}
结果:
![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RcruXLn5-1683167031371)(en-resource://database/738:1)\]](https://i-blog.csdnimg.cn/blog_migrate/34e07d83107fa2145c675fa46c8a6512.png)
### 条件变量
> 互斥锁存在一个缺点就是它只有锁定和未锁定两种状态。如果多个线程访问同一个共享资源,但是不确定何时使用该共享资源。如果在临界区里加入判断语句可以解决。但在复杂情形难以实现。这时就需要一个结构,能在条件成立时触发相应线程,进行变量的修改和访问。
#### 使用实例
> th_a 打印10以内非3倍数的数,th_b打印10以内3的倍数。
#include "threadtest.h" / //动态创建 int pthreadcondinit(pthreadcondt cond, pthreadcondattrt* condattr);
//注销条件变量 int pthreadconddestory(pthreadcondt* cond);
//等待 int pthreadcondwait(pthreadcondt cond, pthreadmutext mutex); //有时等待 int pthreadcondtimmedwait(pthreadcondt cond, pthreadmutext mutex, const struct timespec* time);
//激活一个等待的线程 int pthreadcondsignal(pthreadcondt cond); //激活所有等待线程 int pthreadcondbroadcast(pthreadcondt cond); */
//静态创建 pthreadcondt cond = PTHREADCONDINITIALIZER; pthreadmutext mutex = PTHREADMUTEXINITIALIZER;
void condmyThread1(void); void condmyThread2(void); //条件变量 int i = 0;
#ifdef COND int main(void) { pthreadt ta, tb; /线程创建/ threadcreate(&ta, NULL, condmyThread1, NULL); threadcreate(&tb, NULL, condmyThread2, NULL); /等待线程终止/ pthreadjoin(tb, NULL); /销毁/ pthreadmutexdestroy(&mutex); pthreadcond_destroy(&cond);
return 0; } #endif // COND
void cond_myThread1(void data) {
for (i = 1; i < 10; i++) { pthreadmutexlock(&mutex); if (0 == i % 3) { pthreadcondsignal(&cond); } else { printf("thread1 : %d\n", i); } pthreadmutexunlock(&mutex); sleep(1); } return (void*)0; }
void condmyThread2(void data) { while (i <= 9) { pthreadmutexlock(&mutex); if (0 != i % 3) { pthreadcondsignal(&cond); } else { printf("thread2 : %d\n", i); } pthreadmutex_unlock(&mutex); sleep(1); } return (void*)0; }
结果:
![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BHLWplUS-1683167031372)(en-resource://database/740:1)\]](https://i-blog.csdnimg.cn/blog_migrate/59de8ff4506a9b0b71dbc004591402dd.png)
> 原文发布于 [CSDN](https://blog.csdn.net/weixin_52400878/article/details/130481970)