博客 约 22 分钟

操作系统: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, &param); //获得线程的调度参数 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");

}



结果:
![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Adn0TZUF-1683167031370)](https://i-blog.csdnimg.cn/blog_migrate/10d3c0ac9073ad8b046d8d2414a03589.png)

#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)