Linux 多线程 Pthread 互斥量

阅读了《Unix/Linux系统编程》中关于Pthread的内容,并查阅相关资料,进行了总结
本文介绍了Pthread多线程基本操作与互斥量基本操作

1. POSIX和Pthread线程概念

1.1 POSIX:

POSIX表示可移植操作系统接口(Portable Operating System Interface of UNIX,缩写为 POSIX ),POSIX标准定义了操作系统应该为应用程序提供的接口标准。

一般情况下,应用程序通过应用编程接口(API)而不是直接通过系统调用来编程(即并不需要和内核提供的系统调用来编程)。一个API定义了一组应用程序使用的编程接口。它们可以实现成调用一个系统,也可以通过调用多个系统来实现,而完全不使用任何系统调用也不存在问题。实际上,**API可以在各种不同的操作系统上实现给应用程序提供完全相同的接口,**而它们本身在这些系统上的实现却可能迥异。

比如针对某个系统调用函数,Linux是funcA()函数而Windows是funcB()函数,这就导致了源码级别的不可移植性。如果该程序要从Linux移植到Windows上,就需要把源码中的funcA()函数全部换成funcB()函数,然后重新编译。

posix标准的出现就是为了解决这个问题。linux和windows都要实现基本的posix标准,linux把funcA函数封装成posix_func,windows把funcB函数也封装成posix_func,这样在不同操作系统的开发中都调用posix_func函数即可,程序就在源代码级别可移植了

1.2 Pthread

英语:POSIX Threads,常被缩写为Pthreads。是POSIX的线程标准,定义了创建和操纵线程的一套API

实现POSIX 线程标准的库常被称作Pthreads,Pthreads定义了一套C语言的类型、函数与常量,它以pthread.h头文件和一个线程库实现。

Pthreads API中大致共有100个函数调用,全都以pthread_开头

2. pthread函数API

2.1. 创建线程pthread_create()函数

int pthread_create(pthread_t * pthread_id, 
                   const pthread_attr_t * attr, 
                   void * (*func) (void *), 
                   void * arg)

成功返回0,否则返回出错编号。

参数说明:

  • pthread_id

    该参数是一个指向pthread_t类型(线程标识符类型)的指针,该函数会将新分配的唯一线程ID赋给该指针指向的内容。在Linux中,pthread_id类型是unsigned long int。可以通过pthread_self()函数获得自身线程ID。

    pthread_t pthread_self (void)
    
  • attr

    该参数用来设置线程属性,pthread_attr_t是线程属性类型。在使用该类型变量之前必须进行初始化,在使用后需要释放其资源。

    1. 定义一个pthread属性变量pthread_attr_t attr
    2. pthread_attr_init(&attr)初始化线程属性变量
    3. 设置线程属性并传递给pthread_create函数
    4. 可以通过pthread_attr_destroy(&attr)释放attr资源

    示例:创建一个分离线程

    pthread_attr_t attr;	//定义一个线程属性类型变量
    pthread_attr_init(&attr);	//对该变量进行初始化
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);	//设置线程属性-使该线程无法与其他线程连接
    pthread_create(&id,&attr,func,NULL);	//根据线程属性创建新线程
    pthread_attr_destroy(&attr);	//释放线程资源
    

    如果该参数为NULL,则使用默认属性创建线程。建议使用NULL传递该参数,除非有必要更改线程属性。

    pthread_create(&id,NULL,func,NULL);
    
  • func:

    线程运行函数的起始地址。

  • arg

    运行函数的参数。

2.2 线程比较函数pthread_equal

可以用分配的唯一线程ID来区分线程,但是不应该直接比较线程ID(在不同的系统下,pthread_t的实现类型是不同的,比如在ubuntn下是unsigned long,在solaris系统中是unsigned int,而在FreeBSD上用的是结构体指针。 所以不能直接使用==判断),而应该使用pthread_equal()函数对它们进行比较

int pthread_equal(pthread_t thread1, pthread_t thread2)

如果线程相同返回非0,线程不同返回0

2.3 线程终止函数pthread_exit

void pthread_exit(void * status)

显式的终止线程。status是线程退出状态,0代表正常终止,非0表示异常终止。当函数返回时,被等待线程的资源被收回。如果线程已经结束,那么该函数会立即返回。并且thread指定的线程必须是joinable的。

2.4 线程连接函数pthread_join

int 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
多线程编程中,为了防止多个线程同时访问共享资源而导致的数据竞争问题,需要使用同步机制来实现线程间的协调和互斥。而互斥是一种常用的同步机制,在多线程编程中被广泛使用。 互斥是一种线程同步原语,用于保护共享资源。当一个线程需要访问共享资源时,它需要先获取该资源的互斥。如果该互斥已经被其他线程占用,则当前线程会被阻塞,直到该互斥被释放。一旦该互斥被释放,当前线程就可以获取该互斥,访问共享资源,并将该互斥加锁。当该线程完成对共享资源的访问后,它需要将该互斥解锁,以便其他线程可以获取该互斥继续访问共享资源。 互斥的使用一般涉及到以下四个函数: 1. pthread_mutex_init():初始化互斥; 2. pthread_mutex_lock():加锁互斥; 3. pthread_mutex_unlock():解锁互斥; 4. pthread_mutex_destroy():销毁互斥。 下面是一个简单的例子,展示了如何使用互斥实现线程同步: ``` #include <stdio.h> #include <pthread.h> pthread_mutex_t mutex; // 定义互斥 void *thread_func(void *arg) { pthread_mutex_lock(&mutex); // 加锁互斥 printf("Thread %ld is running.\n", pthread_self()); pthread_mutex_unlock(&mutex); // 解锁互斥 pthread_exit(NULL); } int main(int argc, char *argv[]) { pthread_t t1, t2; pthread_mutex_init(&mutex, NULL); // 初始化互斥 pthread_create(&t1, NULL, thread_func, NULL); pthread_create(&t2, NULL, thread_func, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_mutex_destroy(&mutex); // 销毁互斥 return 0; } ``` 在上面的例子中,我们定义了一个互斥 mutex,然后在线程函数中分别加锁和解锁该互斥。在主函数中,我们创建了两个线程,并等待它们执行完毕后退出程序。需要注意的是,我们必须在程序退出之前销毁该互斥,以免产生内存泄漏。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值