在Linux中创建线程和互斥信号量的使用
- 创建线程说明
在Linux中创建线程非常简单,只需要调用pthread_create函数即可。
我们先来看一下该函数的原型:
#include<pthread.h>
int pthread_create(pthread_t *thread, pthread_addr_t *arr, void* (*start_routine)(void *), void *arg);
我们再来看一下相关形参的定义:
thread:用于返回创建的线程的信息
arr:用于指定的被创建的线程的属性。可以使用NULL,表示使用默认的属性
start_routine:一个函数指针,指向线程被创建后要调用的函数
arg:用于给线程传递参数
除此以外,我们还可以调用pthread_self函数来获取当前线程的ID,调用pthread_join来等待线程的退出。
- 互斥量
互斥量是另一种用于多线程中的同步访问方法,它允许程序锁住某个对象,使得每次只能有一个线程访问它。为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁。
它们的定义与使用信号量的函数非常相似,相关函数如下:
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
它们的意义就如它们的名字所示的那样,成功时返回0,失败时返回错误代码,不过它们并不设置errno。
pthread_mutex_init函数中的参数mutexattr指定互斥量的属性,在这里我们并不关心互斥量的属性,所以把它设置为NULL,使用默认属性即可。同样的,pthread_mutex_lock和pthread_mutex_unlock都是原子操作,如果一个线程调用pthread_mutex_lock试图锁住互斥量,而该互斥量,又被其他线程锁住(占用),则该线程的pthread_mutex_lock调用就会阻塞,直到其他线程对该互斥量进行解锁,该线程才能获得该互斥量,pthread_mutex_lock调用才会返回。
注意,使用互斥量的默认属性,如果程序试图对一个已经加锁的互斥量调用pthread_mutex_lock,程序就会阻塞,而又因为拥有互斥量的这个线程正是现在被阻塞的线程,所以这个互斥量就永远不会被解锁,也就是说,程序就会进入死锁的状态。在使用时要多加注意,确保在同一个线程中,对加锁的互斥再次进行加锁前要对其进行解锁。
闲话少说,我们直接来看一下简单的示范代码:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<pthread.h>
#define MAX_LOOP 4
pthread_mutex_t g_mutex;
//新线程函数体
void* thread_func(void *arg)
{
printf("[Thread] Begin\n");
int i = 0;
while(i < MAX_LOOP)
{
//互斥上锁
pthread_mutex_lock(&g_mutex);
printf("[Thread]i -> %d xxx!\n",i);
sleep(1);
printf("[Thread]i -> %d ooo!\n",i);
//互斥解锁
pthread_mutex_unlock(&g_mutex);
i++;
}
printf("[Thread] Finish\n");
return 0;
}
int main(int argc, char * argv[])
{
//创建互斥信号量
if(pthread_mutex_init(&g_mutex,NULL) != 0)
{
printf("[main]Create the mutex failed!\n");
exit(EXIT_FAILURE);
}
pthread_t thread;
//创建线程,指定线程函数体
pthread_create(&thread,NULL,thread_func,NULL);
printf("[main] Begin to printf information\n");
int i = 0;
while(i < MAX_LOOP)
{
//互斥上锁
pthread_mutex_lock(&g_mutex);
printf("[main]i -> %d xxx!\n",i);
sleep(1);
printf("[main]i -> %d ooo!\n",i);
//互斥解锁
pthread_mutex_unlock(&g_mutex);
i++;
}
void *retval = NULL;
int res = pthread_join(thread, &retval);
if(res != 0)
{
printf("[main]pthread_join failed\n");
}
//销毁互斥信号量
pthread_mutex_destroy(&g_mutex);
printf("main thread finish, id is 0x%X\n",(unsigned)pthread_self());
return 0;
}
运行结果:
root@android:/ # ./cache/simple
[main] Begin to printf information
[Thread] Begin
[main]i -> 0 xxx!
[main]i -> 0 ooo!
[main]i -> 1 xxx!
[main]i -> 1 ooo!
[main]i -> 2 xxx!
[main]i -> 2 ooo!
[main]i -> 3 xxx!
[main]i -> 3 ooo!
[Thread]i -> 0 xxx!
[Thread]i -> 0 ooo!
[Thread]i -> 1 xxx!
[Thread]i -> 1 ooo!
[Thread]i -> 2 xxx!
[Thread]i -> 2 ooo!
[Thread]i -> 3 xxx!
[Thread]i -> 3 ooo!
[Thread] Finish
main thread finish, id is 0x2AB30CDC