Multi-threaded programming learning

The concept of threads and Function Description

In terms of operating system principles, the thread is a path of execution process. All threads are running in the same process space, this also means that multiple threads will share all of the system resources of the process, such as virtual address space, file descriptors, and signal processing, and so on. However, multiple threads in the same process has its own call stack (call stack), register your environment (register context), own thread local storage (thread-local storage). A process can have a lot of threads, each thread in parallel to perform different tasks.Here Insert Picture Description

#include <pthread.h>
iint pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

1, Function Description: pthreand_create () is used to create a thread, and the implementation of the third parameter start_routine pointed to function.
2, parameters:

  • The first parameter is a thread pointer type pthread_t, he used to return thread ID of the thread. Each thread is able to acquire its own thread ID by pthread_self ()
  • The second parameter is the thread of property
  • Start_routine third parameter is a function pointer, it points to the function prototype is void * func (void *), which is a child thread created task to be performed
  • The fourth argument arg is a function of the parameters passed to invoked, if there are multiple parameters to be passed to the child thread package is required to pass in a structure where;

Thread Attributes

typedef struct
{
int detachstate; 线程的分离状态
int schedpolicy; 线程调度策略
struct sched_param schedparam; 线程的调度参数
int inheritsched; 线程的继承性
int scope; 线程的作用域
size_t guardsize; 线程栈末尾的警戒缓冲区大小
int stackaddr_set;
void * stackaddr; 线程栈的位置
size_t stacksize; 线程栈的大小
}pthread_attr_t;
对于线程属性,我们需要设定的是线程的分离状态,如果有必要也需要修改每个线程的栈的大小,每个线程创建后默认是可汇合状态,该状态需要主线程调用pthread_join等待它退出,否则子线程在结束时,内存资源不能得到释放造成内存泄漏,所以我们创建线程时一般会将线程设置为分离状态

线程编码示例

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
void *thread_worker1(void *args);
void *thread_worker2(void *args);

int main (int argc, char **argv)
{
    int shared_var = 1000;
    pthread_t    tid;//定义一个线程
    pthread_attr_t  thread_attr;//定义线程属性

if(pthread_attr_init(&thread_attr))//初始化线程
{
    printf("pthread_attr_init()failure:%s\n",strerror(errno));
    return -1;
}
if(pthread_attr_setstacksize(&thread_attr,120*1024))//设置线程属性栈的大小
{
    printf("pthread_attr_setstacksize()failure:%s\n",strerror(errno));
    return -2;
}
if(pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED))//设置线程为可分离状态
{
    printf("pthread_attr_setdetachstate()failure:%s\n",strerror(errno));
    return -3;
}
pthread_create(&tid,&thread_attr,thread_worker1,&shared_var);//&tid,用来返回该线程的id,第二个参数是线程的属性,第三个参数是子线程要完成的任务,第四个参数是传给所调用的函数的指针
printf("Thread worker1 tid[%ld]created ok\n",tid);

pthread_create(&tid,NULL,thread_worker2,&shared_var);
printf("Thread worker2 tid[%ld]created ok\n",tid);

pthread_attr_destroy(&thread_attr);//用完以后要摧毁

pthread_join(tid,NULL);//线程2需要主线程调用pthread_join等待它退出

while(1)
{
    printf("main thread shared_var:%d\n",shared_var);
    sleep(10);
}
}
void *thread_worker1(void *args)
{
    int  *ptr = (int *)args;
    if( !args )
    {
        printf("%s()get invalid arguments\n", __FUNCTION__);
        pthread_exit(NULL);
    }
    printf("Thread worker1 [%ld]start running..\n",pthread_self());//打印自己的线程id
    while(1)
    {
        printf("+++ %s before shared_var++:%d\n", __FUNCTION__,*ptr);
        *ptr+=1;//*ptr=*ptr+1
        sleep(2);
        printf("+++:%s after sleep shared_var:%d\n", __FUNCTION__,*ptr);
    }
    printf("Thread worker 1 exit...\n");

    return NULL;
}
void *thread_worker2(void *args)
{
    int    *ptr = (int *)args;
    printf("%s()get invalid arguments\n", __FUNCTION__);
    pthread_exit(NULL);

    printf("Thread worker2 [%ld]start running..\n",pthread_self());

    while(1)
    {
        printf("--- %s before shared_var++:%d\n", __FUNCTION__,*ptr);
        *ptr+=1;//* ptr=*ptr+1 
        sleep(2);
        printf("---:%s after sleep shared_var:%d\n", __FUNCTION__,*ptr);
    }
    printf("Thread worker 2 exit...\n");
    return NULL;
}

linux下vim代码运行结果:
Here Insert Picture Description
该代码出现的问题:thread_worker1 在创建后首先开始运行,在开始自加之前值为初始值1000,然后让该值自加后休眠2秒后再打印该值发现不是1001而是1002了。这是由于shared_var 这个变量会被两个子线程同时访问修改致。如果一个资源会被不同的线程访问修改,那么我们把这个资源叫做临界资源,那么对于该资源访问修改相关的代码就叫做临界区。那么怎么解决多个线程之间共享同一个共享资源,是多线程编程需要考虑的一个问题。有关如何解决此临界问题!请关注我下一篇博客!

Released three original articles · won praise 11 · views 272

Guess you like

Origin blog.csdn.net/makunIT/article/details/104605225