zoukankan      html  css  js  c++  java
  • Linux 多线程通信

     摘自资料(linux 与Windows不同)

         线程间无需特别的手段进行通信,由于线程间能够共享数据结构,也就是一个全局变量能够被两个线程同一时候使用。只是要注意的是线程间须要做好同步,一般用mutex。能够參考一些比較新的UNIX/Linux编程的书,都会提到Posix线程编程,比方《UNIX环境高级编程(第二版)》、《UNIX系统编程》等等。 linux的消息属于IPC,也就是进程间通信,线程用不上。

    linux用pthread_kill对线程发信号。 另:windows下不是用post..(你是说PostMessage吗?)进行线程通信的吧?

    windows用PostThreadMessage进行线程间通信,但实际上极少用这样的方法。还是利用同步多一些 LINUX下的同步和Windows原理都是一样的。只是Linux下的singal中断也非常好用。

    用好信号量,共享资源就能够了。

     使用多线程的理由之中的一个是和进程相比,它是一种非常"节俭"的多任务操作方式。我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。而执行于一个进程中的多个线程,它们彼此之间使用同样的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,并且,线程间彼此切换所需的时间也远远小于进程间切换所须要的时间。

      使用多线程的理由之二是线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递仅仅能通过通信的方式进行,这样的方式不仅费时,并且非常不方便。线程则不然,因为同一进程下的线程之间共享数据空间,所以一个线程的数据能够直接为其他线程所用,这不仅快捷,并且方便。当然,数据的共享也带来其他一些问题,有的变量不能同一时候被两个线程所改动,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最须要注意的地方。
    1、简单的多线程程序

       首先在主函数中,我们使用到了两个函数,pthread_create和pthread_join,并声明了一个pthread_t型的变量。
    pthread_t在头文件pthread.h中已经声明,是线程的标示符

       函数pthread_create用来创建一个线程,函数原型:

    extern int pthread_create __P ((pthread_t *__thread, __const pthread_attr_t *__attr,void *(*__start_routine) (void *), void *__arg));

      第一个參数为指向线程标识符的指针,第二个參数用来设置线程属性,第三个參数是线程执行函数的起始地址,最后一个參数是执行函数的參数。若我们的函数thread不须要參数,所以最后一个參数设为空指针。第二个參数我们也设为空指针,这样将生成默认属性的线程。对线程属性的设定和改动我们将在下一节阐述。当创建线程成功时,函数返回0,若不为0则说明创建线程失败,常见的错误返回代码为EAGAIN和EINVAL。前者表示系统限制创建新的线程,比如线程数目过多了;后者表示第二个參数代表的线程属性值非法。创建线程成功后,新创建的线程则执行參数三和參数四确定的函数,原来的线程则继续执行下一行代码。
    函数pthread_join用来等待一个线程的结束。函数原型为:

      extern int pthread_join __P ((pthread_t __th, void **__thread_return));

      第一个參数为被等待的线程标识符,第二个參数为一个用户定义的指针,它能够用来存储被等待线程的返回值。这个函数是一个线程堵塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。一个线程的结束有两种途径,一种是象我们上面的样例一样,函数结束了,调用它的线程也就结束了;还有一种方式是通过函数pthread_exit来实现。它的函数原型为:

      extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));

      唯一的參数是函数的返回代码,仅仅要pthread_join中的第二个參数thread_return不是NULL,这个值将被传递给thread_return。最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。

    2、改动线程的属性
    设置线程绑定状态的函数为pthread_attr_setscope,它有两个參数,第一个是指向属性结构的指针,第二个是绑定类型,它有两个取值:PTHREAD_SCOPE_SYSTEM(绑定的)和PTHREAD_SCOPE_PROCESS(非绑定的)。以下的代码即创建了一个绑定的线程。

    #include
    pthread_attr_t attr;
    pthread_t tid;

    /*初始化属性值,均设为默认值*/
    pthread_attr_init(&attr);
    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);

    pthread_create(&tid, &attr, (void *) my_function, NULL);

    3、线程的数据处理

    和进程相比,线程的最大长处之中的一个是数据的共享性,各个进程共享父进程处沿袭的数据段,能够方便的获得、改动数据。但这也给多线程编程带来了很多问题。我们必须当心有多个不同的进程訪问同样的变量。很多函数是不可重入的,即同一时候不能执行一个函数的多个拷贝(除非使用不同的数据段)。在函数中声明的静态变量经常带来问题,函数的返回值也会有问题。由于假设返回的是函数内部静态声明的空间的地址,则在一个线程调用该函数得到地址后使用该地址指向的数据时,别的线程可能调用此函数并改动了这一段数据。在进程中共享的变量必须用keywordvolatile来定义,这是为了防止编译器在优化时(如gcc中使用-OX參数)改变它们的使用方式。为了保护变量,我们必须使用信号量、相互排斥等方法来保证我们对变量的正确使用。

    4、相互排斥锁

    相互排斥锁用来保证一段时间内仅仅有一个线程在运行一段代码。必要性显而易见:如果各个线程向同一个文件顺序写入数据,最后得到的结果一定是灾难性的


  • 相关阅读:
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    449. Serialize and Deserialize BST
    114. Flatten Binary Tree to Linked List
    199. Binary Tree Right Side View
    173. Binary Search Tree Iterator
    98. Validate Binary Search Tree
    965. Univalued Binary Tree
    589. N-ary Tree Preorder Traversal
    eclipse设置总结
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4035508.html
Copyright © 2011-2022 走看看