linux c++ 多线程编程

简介: 文章参考: http://www.cnblogs.com/forstudy/archive/2012/04/05/2433853.html一. 进程和线程     进程     (1) 系统中程序执行和资源分配的基本单位     (2) 每个...

文章参考: http://www.cnblogs.com/forstudy/archive/2012/04/05/2433853.html

一. 进程和线程

     进程
     (1) 系统中程序执行和资源分配的基本单位
     (2) 每个进程有自己的数据段、代码段和堆栈段
     (3) 在进行切换时需要有比较复杂的上下文切换
 
     线程
     (1) 减少处理机的空转时间,支持多处理器以及减少上下文切换开销, 比创建进程小很多
     (2) 进程内独立的一条运行路线
     (3) 处理器调度的最小单元,也称为轻量级进程
     (4) 一个进程可以有多个线程,有多个线程控制表及堆栈寄存器,共享一个用户地址空间

二. 线程函数
   1. 线程标识
       pthread_t pthread_self();
       返回值: 返回线程ID,linux规定为无符号长整数
   2. 线程相等
       int pthread_equal(pthread_t tid1, pthread_t tid2);
       返回值: 判断两个线程是否相等
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

int main(){
    pthread_t thread_id;

    thread_id=pthread_self(); // 返回调用线程的线程ID
    printf("Thread ID: %lu.\n",thread_id);

    if (pthread_equal(thread_id,pthread_self())) {
        if (thread_id==0) {
            printf("Equal!\n");
        } else {
            printf("Not equal!\n");
        }
        return 0;
    }
}


    3. 创建线程
  int pthread_create(pthread_t *tid,const pthread_attr_t *attr,(void*)(*start_routine)(void*),void *arg);
  参数:
  1)tid, 线程标识符
  2)attr, 线程属性,通常设置为NULL
  3)start_routine, 线程函数
  4)arg, 传递给线程函数的参数
     返回值:
     1). 成功,返回0
     2). 失败,返回错误码
     说明:
     1). 线程创建完成之后,就开始从线程函数入口开始执行
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>

void *thrd_func(void *arg);
pthread_t tid;

int main(){
    if (pthread_create(&tid,NULL,thrd_func,NULL)!=0) {
        printf("Create thread error!\n");
        exit(1);
    }
    sleep(1);  //sleep主线程,保证子线程能够执行成功
    printf("TID in pthread_create function: %lu.\n",tid);
    printf("Main process: PID: %d,TID: %lu.\n",getpid(), pthread_self()); 
    return 0;
}

void *thrd_func(void *arg){
    printf("I am new thread!\n");
    printf("New process:  PID: %d,TID: %lu.\n",getpid(), pthread_self());
    printf("New process:  PID: %d,TID: %lu.\n",getpid(), tid);
    pthread_exit(NULL);
    return 0;
}

    4. 退出线程
       void pthread_exit(void* retVal);
       参数:
       1). retVal,线程结束的返回值,通常设置为NULL
       说明:
       1). 线程函数执行完毕之后当前线程也就退出了,如果使用thread_exit则是主动的退出线程
      
    5. 等待线程
       int pthread_join(pthread_t tid, void** retVal);
       参数:
       1. tid,线程标识符
       2. retVal,用来存储被等阻塞线程的返回值,通常设置为NULL
       返回值:
       1. 成功,返回0
       2. 失败,返回错误码
       说明:
       1. 这是一个线程阻塞函数,调用它的线程将会一直等待被阻塞的线程结束为止。函数返回时,被阻塞的线程资源被回收
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>

void *thrd_func1(void *arg);
void *thrd_func2(void *arg);

int main(){
    pthread_t tid1,tid2;
    void *tret;
    // 创建线程tid1,线程函数thrd_func1
    if (pthread_create(&tid1,NULL,thrd_func1,NULL)!=0) {
        printf("Create thread 1 error!\n");
        exit(1);
    }
    // 创建线程tid2,线程函数thrd_func2
    if (pthread_create(&tid2,NULL,thrd_func2,NULL)!=0) {
        printf("Create thread 2 error!\n");
        exit(1);
    }
    // 主线程等待线程tid1结束
    int retCode = pthread_join(tid1, NULL);
    printf("Thread 1 exit code:%d\n", retCode);
    // 主线程等待线程tid2结束
    pthread_join(tid2, NULL);
    printf("Thread 2 exit code:%d\n", retCode);
    return 0;
}

void *thrd_func1(void *arg){
    printf("Thread 1 returning!\n");
    return ((void *)1); // 自动退出线程
}

void *thrd_func2(void *arg){
    printf("Thread 2 exiting!\n");
    pthread_exit((void *)2);  // 线程主动退出,返回(void *)2
} 

三. 线程同步与互斥
     线程共享进程的资源和地址空间,对这些资源进行操作时,必须考虑线程间同步与互斥问题
     三种线程同步机制
    •互斥锁
    •信号量
    •条件变量
     互斥锁更适合同时可用的资源是惟一的情况,信号量更适合同时可用的资源为多个的情况
    
    1. 互斥锁
  (1) 用简单的加锁方法控制对共享资源的原子操作,只有两种状态: 上锁、解锁
       (2) 可把互斥锁看作某种意义上的全局变量
  (3) 在同一时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程能够对共享资源进行操作
  (4) 若其他线程希望上锁一个已经被上锁的互斥锁,则该线程就会挂起,直到上锁的线程释放掉互斥锁为止
互斥锁保证让每个线程对共享资源按顺序进行原子操作
 
       互斥锁主要包括下面的基本函数:
  互斥锁初始化:pthread_mutex_init()
  互斥锁上锁:pthread_mutex_lock()
  互斥锁判断上锁:pthread_mutex_trylock()
  互斥锁解锁:pthread_mutex_unlock()
  消除互斥锁:pthread_mutex_destroy()
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>

#define THREAD_NUM 3
#define REPEAT_TIMES 5
#define DELAY 4

pthread_mutex_t mutex;

void *thrd_func(void *arg);

int main(){
    pthread_t thread[THREAD_NUM];
    int no;
    void *tret;

    srand((int)time(0));
   //初始化互斥锁  
   pthread_mutex_init(&mutex,NULL);

    for(no=0;no<THREAD_NUM;no++){
        if (pthread_create(&thread[no],NULL,thrd_func,(void*)no)!=0) {
            printf("Create thread %d error!\n",no);
            exit(1);
        }
        else {
            printf("Create thread %d success!\n",no);
    }
   //主线程等待子线程结束 
   for(no=0;no<THREAD_NUM;no++){
        if (pthread_join(thread[no],&tret)!=0){
            printf("Join thread %d error!\n",no);
            exit(1);
        }
        else {
            printf("Join thread %d success!\n",no);
        }
    }
    pthread_mutex_destroy(&mutex);
    return 0;
}

void *thrd_func(void *arg){
    int thrd_num=(int)arg;
    int delay_time,count; 
   //加锁
    if(pthread_mutex_lock(&mutex)!=0) {
        printf("Thread %d lock failed!\n",thrd_num);
        pthread_exit(NULL);
    }

    printf("Thread %d is starting.\n",thrd_num);
    for(count=0;count<REPEAT_TIMES;count++) {
        delay_time=(int)(DELAY*(rand()/(double)RAND_MAX))+1;
        sleep(delay_time);
        printf("\tThread %d:job %d delay =%d.\n",thrd_num,count,delay_time);
    }

    printf("Thread %d is exiting.\n",thrd_num);
    //解锁
   pthread_mutex_unlock(&mutex);

    pthread_exit(NULL);   
}

目录
相关文章
|
4月前
|
机器学习/深度学习 消息中间件 存储
【高薪程序员必看】万字长文拆解Java并发编程!(9-2):并发工具-线程池
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的强力并发工具-线程池,废话不多说让我们直接开始。
182 0
|
7月前
|
存储 Linux API
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
|
5月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
237 67
|
7月前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
7月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
122 26
|
7月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
129 17
|
7月前
|
存储 机器学习/深度学习 编译器
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
|
7月前
|
存储 算法 C++
深入浅出 C++ STL:解锁高效编程的秘密武器
C++ 标准模板库(STL)是现代 C++ 的核心部分之一,为开发者提供了丰富的预定义数据结构和算法,极大地提升了编程效率和代码的可读性。理解和掌握 STL 对于 C++ 开发者来说至关重要。以下是对 STL 的详细介绍,涵盖其基础知识、发展历史、核心组件、重要性和学习方法。
|
7月前
|
存储 安全 算法
深入理解C++模板编程:从基础到进阶
在C++编程中,模板是实现泛型编程的关键工具。模板使得代码能够适用于不同的数据类型,极大地提升了代码复用性、灵活性和可维护性。本文将深入探讨模板编程的基础知识,包括函数模板和类模板的定义、使用、以及它们的实例化和匹配规则。
|
9月前
|
安全 Java API
【JavaEE】多线程编程引入——认识Thread类
Thread类,Thread中的run方法,在编程中怎么调度多线程