[linux]进程(八)---线程概念

线程

概念:
线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),
进程的所有信息对该进程的所有线程是共享的,包括程序文本,程序的全部内存,堆,栈和文件描述符。

线程标识:
进程ID在整个系统中是唯一的,用pid_t数据类型表示,
线程ID只在它所属的进程环境中有效,用pthread_t数据类型表示,用 pthread_t pthread_self(void);来获得自身线程ID。

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <pthread.h>
 4
 5 int main(){
 6     pthread_t thread_id;
 7
 8     thread_id=pthread_self(); // 返回调用线程的线程ID
 9     printf("Thread ID: %lu.\n",thread_id);
10
11     if (pthread_equal(thread_id,pthread_self())) {
12 //    if (thread_id==0) {
13         printf("Equal!\n");
14     } else {
15         printf("Not equal!\n");
16     }
17     return 0;
18 }

线程的创建:
使用pthread_creat()函数:返回值:成功-0,失败-返回错误编号,可以用strerror(errno)函数得到错误信息

#include<pthread.h>
int pthread_create (pthread_t *__restrict __newthread,//新创建的线程ID
               __const pthread_attr_t *__restrict __attr,//线程属性
               void *(*__start_routine) (void *),//新创建的线程从start_routine开始执行
               void *__restrict __arg)//执行函数的参数  

线程的终止:
线程从执行函数返回,返回值是线程的退出码
线程被同一进程的其他线程取消
调用pthread_exit()函数退出。这里不是调用exit,因为线程调用exit函数,会导致线程所在的进程退出。
线程创建,线程终止实例:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

pthread_mutex_t mylock=PTHREAD_MUTEX_INITIALIZER;
int num = 0;
void *add(void *arg)
{

	int i = 0, tmp;
	for(;i<10;i++)
	{
		pthread_mutex_lock(&mylock);
		tmp=num+1;
		num=tmp;
		printf("add result is :%d\n",num);
		pthread_mutex_unlock(&mylock);
	}
	return ((void*)0);
}

void *sub(void *arg)
{
	int i=0,tmp;
	for(;i<10;i++)
	{
		pthread_mutex_lock(&mylock);
		tmp=num-1;
		num=tmp;
		printf("sub result is:%d\n",num);
		pthread_mutex_unlock(&mylock);
	}
	return ((void*)0);
}

int main(int argc,char **argv)
{
	pthread_t tid1,tid2;
	int err;
	void *tret;
	err=pthread_create(&tid1,NULL,add,NULL);
	if (err != 0)
	{
		printf("pthread_creat error :%s\n",strerror(err));
		exit(-1);
	}
	err=pthread_create(&tid2,NULL,sub,NULL);
	if(err != 0)
	{
		printf("pthread_creat error :%s\n",strerror(err));
		exit(-1);
	}
	err=pthread_join(tid1,&tret);
	if (err != 0)
	{
		printf("can not join with thread1: %s\n",strerror(err));
	}
	printf("thread 1 exit code\n");
	err=pthread_join(tid2,&tret);
	printf("thread 2 exit code \n");
	return 0;
}

编译的时候需要加上-lpthread,

2,线程同步:

点击打开链接

(一)互斥量:
两种方式初始化,第一种:赋值为常量PTHREAD_MUTEX_INITIALIZER;第二种,当互斥量为动态分配是,使用pthread_mutex_init函数进行初始化,使用pthread_mutex_destroy函数销毁。

#include<pthread.h>
int pthread_mutex_init (pthread_mutex_t *__mutex,
                   __const pthread_mutexattr_t *__mutexattr);
int pthread_mutex_destroy (pthread_mutex_t *__mutex);  

#include<pthread.h>
int pthread_mutex_init (pthread_mutex_t *__mutex,
			       __const pthread_mutexattr_t *__mutexattr);
int pthread_mutex_destroy (pthread_mutex_t *__mutex);返回值:成功-0,失败-错误编号
加解锁
加锁调用pthread_mutex_lock,解锁调用pthread_mutex_unlock。
[cpp] view plaincopyprint?
#include<pthread.h>
int pthread_mutex_lock (pthread_mutex_t *__mutex);
int pthread_mutex_unlock (pthread_mutex_t *__mutex);

使用互斥量应该避免死锁,如一个线程试图对同一个互斥量加锁两次,自身会陷入死锁状态,另外一个情况是一个程序中
一个线程占用一个互斥量但是试图获取第二个互斥量,但是另外一个线程已经占用第二个互斥量但是试图获取第一个互斥量。
可以用pthread_mutex_trylock()函数防止死锁
具体说一下trylock函数, 这个函数是非阻塞调用模式, 也就是说, 如果互斥量没被锁住, trylock函数将把互斥量加锁, 并获得对共享资源的访问权限;
 如果互斥量被锁住了, trylock函数将不会阻塞等待而直接返回EBUSY, 表示共享资源处于忙状态

(二)读写锁

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#define DEBUG 1   

int num=0;
pthread_mutex_t mylock=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t qready=PTHREAD_COND_INITIALIZER;
void * thread_func(void *arg)
{
    int i=(int)arg;
    int ret;
    sleep(5-i);//线程睡眠,然最先生成的线程,最后苏醒
    pthread_mutex_lock(&mylock);//调用pthread_cond_wait前,必须获得互斥锁
    while(i!=num)
    {
#ifdef DEBUG
        printf("thread %d waiting\n",i);
#endif
        ret=pthread_cond_wait(&qready,&mylock);//该函数把线程放入等待条件的线程列表,然后对互斥锁进行解锁,这两部都是原子操作。并且在pthread_cond_wait返回时,互斥量再次锁住。
        if(ret==0)
        {
#ifdef DEBUG
            printf("thread %d wait success\n",i);
#endif
        }else
        {
#ifdef DEBUG
            printf("thread %d wait failed:%s\n",i,strerror(ret));
#endif
        }
    }
    printf("thread %d is running \n",i);
    num++;
    pthread_mutex_unlock(&mylock);//解锁
    pthread_cond_broadcast(&qready);//唤醒等待该条件的所有线程
    return (void *)0;
}
int main(int argc, char** argv) {  

    int i=0,err;
    pthread_t tid[4];
    void *tret;
    for(;i<4;i++)
    {
        err=pthread_create(&tid[i],NULL,thread_func,(void *)i);
        if(err!=0)
        {
            printf("thread_create error:%s\n",strerror(err));
            exit(-1);
        }
    }
    for (i = 0; i < 4; i++)
    {
        err = pthread_join(tid[i], &tret);
        if (err != 0)
        {
            printf("can not join with thread %d:%s\n", i,strerror(err));
            exit(-1);
        }
    }
    return 0;
}

(三)条件变量
为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。

时间: 2024-10-05 05:00:18

[linux]进程(八)---线程概念的相关文章

windows和linux进程与线程的理解

对于windows来说,进程和线程的概念都是有着明确定义的,进程的概念对应于一个程序的运行实例(instance),而线程则是程序代码执行的最小单元.也就是说windows对于进程和线程的定义是与经典OS课程中所教授的进程.线程概念相一致的. 提供API,CreateThread()用于建立一个新的线程,传递线程函数的入口地址和调用参数给新建的线程,然后新线程就开始执行了. windows下,一个典型的线程拥有自己的堆栈.寄存器(包括程序计数器PC,用于指向下一条应该执行的指令在内存中的位置),

Linux进程或线程绑定到CPU

Linux进程或线程绑定到CPU 为了让程序拥有更好的性能,有时候需要将进程或线程绑定到特定的CPU,这样可以减少调度的开销和保护关键进程或线程. 进程绑定到CPU Linux提供一个接口,可以将进程绑定到特定的CPU: #include <sched.h> int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask); int sched_getaffinity(pid_t pid, size_t cpu

Linux 进程、线程运行在指定CPU核上

/******************************************************************************** * Linux 进程.线程运行在指定CPU核上 * 说明: * affinity参数决定了进程.线程是否可在CPU多核之间切换,当然,并不是说就不进行 * 线程切换. * * 2017-9-22 深圳 龙华樟坑村 曾剑锋 *********************************************************

linux 进程 VS 线程

在进行编程模型选择时,总是要对进程和线程的优缺点进行对比,才能做出决定.这里对常用的对比纬度进行了总结,如有新发现,我会更新. linux 进程 VS 线程

Linux进程和线程的比较

进程与线程 参考:http://www.cnblogs.com/blueclue/archive/2010/07/16/1778855.html 首先比较Linux进程和线程的创建的区别,以此展开: 创建进程:(1)调用fork(),为子进程新建内核栈.pthread_info和task_struct,复制父进程的大部分的参数,采用写时复制(copy-on-write)辅助父进程的资源,修改子进程如pid.ppid等重要资源.(2)调用exec()为子进程分配地址空间,载入执行程序. 创建线程:

探究Linux进程及线程堆栈专题&lt;一&gt;

“你定义了那么多全局变量,系统才给你分配了几百KB,这样做是不是太耗内存了?”,一同学问道. 老早就听说嵌入式系统各种资源有限啊,不能分配大空间啊要注意节约资源之类的(...貌似米神4的配置要完爆我的thinkpad了...).那是不是全局变量的使用真的会占用很大系统内存,而系统真的才分配几百KB空间给我呢? 我不信,所以我要尝试一下: 全局变量,肯定是要占用内存的,但无论是不是全局变量,只要是已定义的变量都会占用内存,这个和是否是全局的没啥关系,只是占用的区域不一样而已(详见APUE存储器安排

linux进程、线程(or子进程)、资源占用查看

#  linux进程.线程(or子进程).资源占用查看 查看进程: ps -ef | more  (-e:所有进程,-f:全格式) ++++++++++++++++++++++++++++++++++++ + UID :用户ID                     + + PID :进程ID                           + + PPID :父进程ID                                                 + + C :CPU占

[linux]进程(一)--基本概念

1,进程的基本概念简单来说进程就是执行期的程序,但是同时进程也不至于此,它还包括了其它资源(如打开的文件,挂起的信号等等)Linux是一个多任务多用户操作系统,一个任务(task)就是一个进程(process),即进程=任务,在linux系统中,进程和线程共享一系列的资源(地址空间,文件,信号,名字空间等) 2,进程的标识; 每个进程都有一个独一无二的结构体即struct task_struct,一个进程相关的所有信息都可以在该结构体里标识,每一个进程的task_struct又组成了一个任务队列

Linux进程与线程的区别

cnyinlinux 本文较长,耐心阅读,必有收获! 进程与线程的区别,早已经成为了经典问题.自线程概念诞生起,关于这个问题的讨论就没有停止过.无论是初级程序员,还是资深专家,都应该考虑过这个问题,只是层次角度不同罢了.一般程序员而言,搞清楚二者的概念,在工作实际中去运用成为了焦点.而资深工程师则在考虑系统层面如何实现两种技术及其各自的性能和实现代价.以至于到今天,Linux内核还在持续更新完善(关于进程和线程的实现模块也是内核完善的任务之一). 本文将以一个从事Linux平台系统开发的程序员角

小何讲进程: Linux进程的基本概念

1.  进程定义 进程是操作系统理论的核心与基础,操作系统中的许多概念都和进程相关. 进程的定义 ,进程有过各种各样的定义,现列举较为著名的几种. 进程是一个独立的可调度的活动: 进程是一个抽象实体,当它执行某个任务时,要分配和释放各种资源: 进程是可以并行执行的计算单位: 进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动: 进程是一个程序的一次执行过程,同时也是资源分配的最小单元. 进程和程序是有本质区别的: 程序是静态的,它是一些保存在磁盘上的指令的有序集合,没有任何执行的概念