C语言如何理解和使用多线程?用法示例和解释

2021年3月27日15:32:12 发表评论 1,168 次浏览

什么是线程?

线程是进程中的单个序列流。因为线程具有进程的一些属性,所以它们有时被称为轻量级进程。

进程和线程之间有什么区别?

线程不像进程那样彼此独立, 因此线程与其他线程共享它们的代码段, 数据段和OS资源(如打开的文件和信号)。但是, 与进程一样, 线程具有其自己的程序计数器(PC), 寄存器集和堆栈空间。

为什么要使用多线程

线程是通过并行改进应用程序的流行方法。例如, 在浏览器中, 多个选项卡可以是不同的线程。 MS word使用多个线程, 一个线程格式化文本, 其他线程处理输入, 等等。

由于以下原因, 线程的运行速度比进程快:

1)线程创建要快得多。

2)线程之间的上下文切换要快得多。

3)线程可以轻松终止

4)线程之间的通讯更快。

查看http://www.personal.kent.edu/~rmuhamma/OpSystems/Myos/threads.htm获取更多细节。

我们可以用C编写多线程程序吗?

与Java不同,该语言标准不支持多线程。POSIX Threads(或Pthreads)是用于线程的POSIX标准。pthread的实现可以通过gcc编译器实现。

一个简单的C程序来演示pthread基本功能的使用

请注意, 下面的程序只能使用带有pthread库的C编译器进行编译。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>  //Header file for sleep(). man 3 sleep for details.
#include <pthread.h>
  
// A normal C function that is executed as a thread 
// when its name is specified in pthread_create()
void *myThreadFun( void *vargp)
{
     sleep(1);
     printf ( "Printing GeeksQuiz from Thread \n" );
     return NULL;
}
   
int main()
{
     pthread_t thread_id;
     printf ( "Before Thread\n" );
     pthread_create(&thread_id, NULL, myThreadFun, NULL);
     pthread_join(thread_id, NULL);
     printf ( "After Thread\n" );
     exit (0);
}

在main()中, 我们声明了一个名为thread_id的变量, 其类型为pthread_t, 它是用于标识系统中线程的整数。声明thread_id之后, 我们调用pthread_create()函数创建一个线程。

pthread_create()接受4个参数。

第一个参数是此函数设置的指向thread_id的指针。

第二个参数指定属性。如果该值为NULL, 则应使用默认属性。

第三个参数是要创建的线程要执行的函数的名称。

第四个参数用于将参数传递给函数myThreadFun。

线程的pthread_join()函数等效于进程的wait()。对pthread_join的调用将阻塞调用线程, 直到标识符等于第一个参数的线程终止。

上面的程序如何编译?

要使用gcc编译多线程程序, 我们需要将其与pthreads库链接。以下是用于编译程序的命令。

gfg@ubuntu:~/$ gcc multithread.c -lpthread
gfg@ubuntu:~/$ ./a.out
Before Thread
Printing GeeksQuiz from Thread 
After Thread
gfg@ubuntu:~/$

>一个C程序来显示具有全局变量和静态变量的多个线程

如上所述, 所有线程共享数据段。全局变量和静态变量存储在数据段中。因此, 它们被所有线程共享。下面的示例程序进行了演示。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
  
// Let us create a global variable to change it in threads
int g = 0;
  
// The function to be executed by all threads
void *myThreadFun( void *vargp)
{
     // Store the value argument passed to this thread
     int *myid = ( int *)vargp;
  
     // Let us create a static variable to observe its changes
     static int s = 0;
  
     // Change static and global variables
     ++s; ++g;
  
     // Print the argument, static and global variables
     printf ( "Thread ID: %d, Static: %d, Global: %d\n" , *myid, ++s, ++g);
}
  
int main()
{
     int i;
     pthread_t tid;
  
     // Let us create three threads
     for (i = 0; i < 3; i++)
         pthread_create(&tid, NULL, myThreadFun, ( void *)&tid);
  
     pthread_exit(NULL);
     return 0;
}
gfg@ubuntu:~/$ gcc multithread.c -lpthread
gfg@ubuntu:~/$ ./a.out
Thread ID: 3, Static: 2, Global: 2
Thread ID: 3, Static: 4, Global: 4
Thread ID: 3, Static: 6, Global: 6
gfg@ubuntu:~/$

请注意, 以上是显示线程如何工作的简单示例。在线程中访问全局变量通常不是一个好主意。如果线程2优先于线程1并且线程1需要更改变量, 该怎么办。实际上, 如果需要多个线程访问全局变量, 则应使用互斥锁对其进行访问。

参考文献:

http://www.csc.villanova.edu/~mdamian/threads/posixthreads.html

如果发现任何不正确的地方, 或者想分享有关上述主题的更多信息, 请发表评论。

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: