深入理解Linux多线程编程中的全局变量问题 (linux多线程 全局变量)

Linux 多线程编程是一种复杂的编程方式,它与传统的单线程编程方式有着明显的不同。在多线程编程中,一个程序可以同时执行多个任务,这些任务可以在一个或者多个进程间进行切换。但是,多线程编程也面临着许多挑战,比如全局变量数据共享问题。

在本文中,我们将探讨在 Linux 多线程编程中的全局变量问题,包括定义全局变量、全局变量的作用域以及如何合理使用全局变量。

定义全局变量

在多线程编程中,我们通常需要在不同的线程享数据。全局变量是一种最常用的共享数据路径,因为它可以被所有进程访问。在 Linux 中,我们可以通过将变量定义在文件的头文件中来定义全局变量。

例如:

“`c

int global_var;

“`

在这个例子中,我们定义了一个名为 global_var 的整型变量作为全局变量。在多个线程之间,可以通过访问这个全局变量来共享数据。

全局变量的作用域

在使用全局变量时需要注意作用域的问题。

在程序中,有不同的作用域范围,从而影响了变量的可见性。在多线程编程中,我们需要将全局变量的作用域限定在各个线程中,以避免线程之间的竞争问题。

比如,我们可以在不同的函数中定义同名的全局变量。这些变量之间是没有任何影响的,因为它们的作用域范围不同。

例如,我们在 file1.c 中定义了一个全局变量:

“`c

int num1 = 10;

“`

在另一个文件 file2.c 中,我们定义了一个同名的全局变量:

“`c

int num1 = 20;

“`

在这种情况下,num1 可以分别被 file1.c 和 file2.c 中的代码访问,但它们之间没有任何关系。

在多线程编程中,我们可以通过将全局变量定义为静态,来限制其作用域只在一个线程中。

例如:

“`c

static int global_var;

“`

这个定义告诉编译器,全局变量 global_var 只能在当前文件的作用域范围内使用。这可以避免在多个线程之间出现全局变量的竞争问题。

合理使用全局变量

全局变量虽然方便,但在多线程编程中,使用全局变量也有可能引起竞争问题。在多个线程同时修改一个全局变量时,有可能导致数据错乱或者程序崩溃。

因此,在多线程编程中,我们需要合理地使用全局变量,尽可能避免在不同线程中修改同一个全局变量。一些常用的方法包括:

1. 在不同线程之间传递变量通过参数传递的方式,而不是使用全局变量。

2. 如果必须使用全局变量,需要使用加锁技术来保护全局变量的访问。只有在一个线程获取到了锁的情况下,才能修改这个全局变量。

3. 在编写程序时,应当尽可能地避免使用全局变量,采用局部变量来代替。

结论

在 Linux 多线程编程中,全局变量的问题是需要注意的。全局变量可以方便地共享数据,但同时也需要注意变量的作用域和安全性。我们需要在编写程序时,根据实际情况合理地使用全局变量,尽可能地避免出现竞争问题。

相关问题拓展阅读:

如何使用 linux下多线程中条件变量

使用条件变量更大的好处是可以避免忙等。相当与多线程中的信号。

  条件变量是线程中的东西就是等待某一条件的发生和信号一样

  以下是说明

  ,条件变量使我们可以睡眠等待某种条件出现。

  条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待”条件变量的条件成立”而挂起;另一个线程使”条件成立”(给出条件成立信号)。为了防止槐凳竞争,条件变量的使用总是和一个互斥锁结合在一起。

  条件变量类型为pthread_cond_t

  创建和注销

  条件变量和互斥锁一样,都有静态动态两种创建方式,静态方式使用PTHREAD_COND_INITIALIZER常量,如下:

  pthread_cond_t

cond=PTHREAD_COND_INITIALIZER

  动态方式调用pthread_cond_init()函数,API定义如下:

  int

pthread_cond_init(pthread_cond_t

*cond,

pthread_condattr_t

*cond_attr)

  尽管POSIX标准中为条件变量定义了属性,但在LinuxThreads中没有实现,因此cond_attr值通常为NULL,且被忽略。

  注销一个条件变量需要调用pthread_cond_destroy(),只有在没有线程在该条件变量上等待的时候才能注销这个条件变量,否则返回EBUSY。API定义如下:

  int

pthread_cond_destroy(pthread_cond_t

*cond)

  等待和激发

  int

pthread_cond_wait(pthread_cond_t

*cond,

pthread_mutex_t

*mutex)

  int

pthread_cond_timedwait(pthread_cond_t

*cond,

pthread_mutex_t

*mutex,

const

struct

timespec

*abstime)

  等待条件有两种方式:无条件等待pthread_cond_wait()和计时等待pthread_cond_timedwait(),其中计时等待方式如果在给定时刻前条件没有满足,则返回ETIMEOUT,结束等待,其中abstime以与time()系统调用相同意义的绝对时间形式出现,0表示格林尼治时间1970年1月1日0时0分0秒。

  使用绝对时间而非相对时间的优点是吵明。如果函数提前返回(很可能因为捕获了一个信号,)

  无论哪种等待方式,都必须和一个互斥锁配合,以防止多个线程同时请求pthread_cond_wait()(或pthread_cond_timedwait(),下同)的竞争条件(Race

Condition)。mutex互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP),且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),而在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁。在条件满足从而离开pthread_cond_wait()之前,mutex将被重新加锁,以与进入pthread_cond_wait()前的加锁动作对应。

  激发条件有两种形式,pthread_cond_signal()激活铅碰旅一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个;而pthread_cond_broadcast()则激活所有等待线程。

  其他

  pthread_cond_wait()和pthread_cond_timedwait()都被实现为取消点,因此,在该处等待的线程将立即重新运行,在重新锁定mutex后离开pthread_cond_wait(),然后执行取消动作。也就是说如果pthread_cond_wait()被取消,mutex是保持锁定状态的,因而需要定义退出回调函数来为其解锁。

在网上看到这个系列的

文章对Linux下的POSIX线程编程方法阐述的十分的清晰,小弟目前关心要学习线程同步中的条件变量的使用方法,转载一下呵呵……

互斥对象是线程程序必需的工具,但它们并非万能的。例如,如果线程正在侍者等待共享数据内某个条件出现,那会发生什么呢?代码可以反复对互斥对象锁定和解锁, 以检查值的任何变化。同时,还要快速将互斥对象解锁,以便其它线程能够进行任何必需的更改。这是一种非常可怕的方法,因为线程需要在合理的时间范围内频繁 地循环检测变化。

在每次检查之间,可以让调用线程短暂地进入睡眠,比如睡眠三秒钟,但是因此线程代码就无法最快作出响应。真正需要的是这样一种方法,当线程在等待满足某些 条件时使线程进入睡眠状态。一旦条件满足,还需要一种方法以唤醒因等待满足特定条件而睡眠的线程。如果能够做到这一点,线程代码将是非常高效的,并且不会 占用宝贵的互斥对象锁。这正是 POSIX 条件变量能做的事!

本文是 POSIX 线程三部曲系列的最后一部分,Daniel 将详细讨论如何使用条件变量。条件变量是 POSIX 线程结构,可以让您在遇到某些条件时“唤醒”线程。可以将它们看作是一种线程安全的信号发送。Daniel 使用目前您所学到的知识实现了一个多线程工作组应用程序,本文将围绕着这一示例而进行讨论。

条件变量详解

在 上一篇文章结 束时,我描述了一个比较特殊的难题:如果线程正在等待某个特定条件发生,它应该如何处理这种情况?它可以重复对互斥对象锁定和解锁,每次都会检查共享数据 结构,以查找某个值。但这是在浪费时间和资源,而且这种繁忙查询的效率非常低。解决这个问题的更佳方法是使用 pthread_cond_wait() 调用来等待特殊条件发生。

了解 pthread_cond_wait() 的作用非常重要 — 它是 POSIX 线程信号发送系统的核心,也是最难以理解的部分。

首先,让我们考虑以下情况:线程为查看已链接列表而锁定了互斥对象,然而该列表恰巧是空的。这一特定线程什么也干不了 — 其设计意图是从列表中除去节点,但是现在却没有节点。因此,它只能:

锁定互斥对象时,线程将调用 pthread_cond_wait(&mycond,&mymutex)。pthread_cond_wait() 调用相当复杂,因此我们每次只执行它的一个操作。

pthread_cond_wait() 所做的之一件事就是同时对互斥对象解锁(于是其它线程可以修改已链接列表),并等待条件 mycond 发生(这样当 pthread_cond_wait() 接收到另一个线程的氏袜“信号”时,它将苏醒)。现在互斥对象已被解锁,其它线程可以访问和修改已链接列表,可能还会添加项。

此 时,pthread_cond_wait() 调用还未返回。对互斥对象解锁会立即发生,但等待条件 mycond 通常是一个阻塞操作,这意味着线程将睡眠,在它苏醒之前不会消耗 CPU 周期。这正是我们期待发生的情况。线程将一直睡眠,直到特定条件发生,在这期间不会发生任何浪费 CPU 时间的繁忙查询。从线程的角度来看,它只是在等待 pthread_cond_wait() 调用返回。

现在继续说明,假设 另一个线程(称作“2 号线程”)锁定了 mymutex 并对已链接列表添加了一项。在对互斥对象解锁之后,2 号线程会立即调用函数 pthread_cond_broadcast(&mycond)。此操作之后,2 号线程将使所有等待 mycond 条件变量的线程立即苏醒。这意味着之一个线程(仍处于 pthread_cond_wait() 调用中)现在将苏醒。

现 在,看一下之一个线程发生了什么。您可能会认为在 2 号线歼谈激程调用 pthread_cond_broadcast(&mymutex) 之后,1 号线程的 pthread_cond_wait() 会立即返回。不是那样!实际上,pthread_cond_wait() 将执行最后一个操作:重新锁定 mymutex。一旦 pthread_cond_wait() 锁定了互斥对象,那么它将返回并允许 1 号线程继续执行。那时,它可以马上检查列表,查看它所感兴趣的更改。

关于linux多线程 全局变量的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 深入理解Linux多线程编程中的全局变量问题 (linux多线程 全局变量)