3-同步与并发-同步1

preview
需积分: 0 0 下载量 36 浏览量 更新于2022-08-03 收藏 21.51MB PDF 举报
在多线程编程中,同步是确保多个线程正确交互的关键概念,避免数据竞争和其他并发问题。本篇将深入探讨同步的概念以及信号的使用。 1. 信号的介绍(Introduction to Signals) 信号是一种进程间通信(IPC)机制,用于通知进程发生了某些事件或异常情况。在Unix-like系统中,信号可以由操作系统发送,也可以由进程自身产生。例如,SIGINT(中断)信号通常用于响应用户按下Ctrl+C,而SIGSEGV(段错误)则表示进程尝试访问无效内存。信号处理可以是同步的,即立即执行;也可以是异步的,通过信号处理函数来处理。 2. 同步(Synchronization) 同步是指控制多个线程对共享资源的访问,以防止数据不一致和竞态条件。常见的同步原语包括互斥锁(mutexes)、信号量(semaphores)、条件变量(condition variables)和读写锁(read-write locks)。这些工具帮助确保在特定时刻只有一个线程可以访问共享数据,或者允许多个线程同时读取但限制写入。 3. 共享变量(Shared Variables) 在C语言的多线程程序中,哪些变量是共享的呢?答案并非像“全局变量是共享的”,“栈变量是私有的”那么简单。一个变量x如果被多个线程引用,那么它就是共享的。这涉及到内存模型、变量实例映射到内存的方式以及可能引用这些实例的线程数量。 4. 线程内存模型 概念上,多个线程在一个进程中运行,每个线程有自己的独立线程上下文,包括线程ID、栈、栈指针、程序计数器(PC)、条件码和通用寄存器。所有线程共享剩余的进程上下文,如代码、数据、堆和共享库段的虚拟地址空间,以及打开的文件和安装的处理器。实际上,虽然寄存器值是真正分离且受保护的,但虚拟内存总是共享的,任何线程都可以读写其他线程的栈。这种概念模型和操作模型之间的不匹配是混淆和错误的来源。 5. 示例程序说明共享 下面的示例程序展示了如何通过全局指针变量`ptr`间接地使同行线程引用主线程的栈。在这个例子中,`ptr`指向两个字符串数组`msgs`,每个线程根据其ID(`myid`)访问`ptr`并打印相应的消息,同时更新静态变量`cnt`的值。这显示了即使栈变量(如`cnt`)是静态的,也可能成为共享资源。 6. 变量实例映射到内存 - 全局变量:在程序开始执行时分配,位于数据段或BSS段,对所有线程可见。 - 局部静态变量:尽管它们在函数内部声明,但它们在整个程序的生命周期中只初始化一次,因此在多线程环境中也是共享的。 - 栈变量:通常被认为是线程私有的,但由于栈在内存中的布局,通过全局指针间接访问栈变量可能导致共享行为。 理解这些基本概念对于编写安全的多线程程序至关重要,因为不当的同步可能导致难以调试的错误。在实际编程中,应谨慎使用共享变量,并确保使用适当的同步机制来保护它们。