在Linux中创建线程和互斥信号量的使用

在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

猜你喜欢

转载自blog.csdn.net/daoliting5268/article/details/86626161
今日推荐