type
status
summary
date
slug
tags
category
icon
password
在 Linux 中,线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。线程可以与同属一个进程的其他线程共享进程资源,如内存空间、文件描述符等,但每个线程也有自己的程序计数器、寄存器和栈空间,以便独立执行任务。
线程的概念
- 轻量级:线程是轻量级的进程,创建和切换线程的开销比进程小。这是因为线程共享进程的大部分资源,不需要像进程那样分配独立的资源。
- 并发执行:线程可以与其他线程并发执行,提高程序的执行效率。例如,在多线程服务器中,可以为每个客户端请求创建一个线程来处理,从而实现同时处理多个请求。
- 共享资源:同一进程内的线程可以共享进程的全局变量、文件描述符、内存空间等资源。这使得线程间的通信和数据共享更加方便,但也需要注意同步和互斥问题,以避免资源冲突和数据不一致。
线程与进程的区别
- 资源拥有:
- 进程:拥有独立的资源集合,包括内存空间、文件描述符、全局变量等。进程间的资源是隔离的,不能直接共享。
- 线程:共享所属进程的大部分资源,如内存空间和文件描述符等,但每个线程有自己的程序计数器、寄存器和栈空间。
- 创建和销毁:
- 进程:创建和销毁进程的开销较大,需要分配和回收独立的资源。
- 线程:创建和销毁线程的开销较小,只需分配少量的资源,如栈空间等。
- 通信方式:
- 进程:进程间的通信需要通过进程间通信机制,如管道、信号、消息队列、共享内存等,实现起来相对复杂。
- 线程:线程间的通信可以通过直接访问共享资源来实现,如共享内存和全局变量等,通信更加方便和高效,但也需要注意同步和互斥问题。
- 调度单位:
- 进程:操作系统调度的基本单位是进程,进程的切换开销较大。
- 线程:线程是操作系统调度的基本单位,线程的切换开销较小,可以更细粒度地进行调度,提高系统的并发性能。
- 独立性:
- 进程:进程是独立的运行单位,拥有独立的地址空间和资源,一个进程崩溃不会影响其他进程。
- 线程:线程是依赖于进程的,一个进程崩溃可能会导致其所有线程崩溃,因为线程共享进程的资源和地址空间。
线程的应用场景
- 多任务处理:如多线程服务器,可以同时处理多个客户端请求。
- 提高程序效率:通过并发执行多个线程,可以充分利用多核 CPU 的计算能力,提高程序的执行效率。
- 响应式程序:如图形用户界面程序,可以使用一个线程处理用户界面,另一个线程处理后台任务,使程序更加响应用户操作。
总之,线程是进程中的实际运作单位,具有轻量级、共享资源和并发执行的特点,与进程相比,在资源拥有、创建和销毁、通信方式、调度单位和独立性等方面存在显著区别。合理使用线程可以提高程序的效率和响应性,但也需要注意线程间的同步和互斥问题,以避免资源冲突和数据不一致。
线程控制
在 Linux 中,线程的控制、创建、终止和等待是多线程编程中的基本操作。以下是这些操作的详细介绍:
线程控制
线程控制是指对线程的运行状态进行管理和控制,包括线程的创建、执行、暂停、恢复和终止等操作。线程控制通常通过线程库(如 POSIX 线程库 pthreads)提供的函数来实现。
线程创建
在 Linux 中,可以使用
pthread_create
函数来创建一个新线程。该函数的基本语法如下:- 参数说明:
thread
:指向pthread_t
类型变量的指针,用于存储新创建线程的线程 ID。attr
:指向pthread_attr_t
类型的指针,用于设置线程属性(如栈大小、调度策略等)。如果设置为NULL
,则使用默认属性。start_routine
:新线程的入口函数,类型为void* (*)(void*)
。该函数将在线程启动后执行。arg
:传递给start_routine
函数的参数,类型为void*
。
- 返回值:如果创建成功,返回
0
;否则返回错误码。
线程终止
线程的终止可以通过以下几种方式实现:
- 自然终止:线程执行完其入口函数后自然终止。
- 显式终止:线程可以通过调用
pthread_exit
函数显式终止自己。该函数的基本语法如下: retval
:线程退出时返回的值,可以被其他等待该线程的线程获取。
- 被其他线程取消:一个线程可以通过调用
pthread_cancel
函数请求取消另一个线程。被取消的线程在执行到取消点时会终止。
线程等待
线程等待是指一个线程等待另一个线程完成其执行。在 Linux 中,可以使用
pthread_join
函数来实现线程等待。该函数的基本语法如下:- 参数说明:
thread
:要等待的线程的线程 ID。retval
:指向void*
类型变量的指针,用于存储被等待线程的返回值。如果不需要获取返回值,可以设置为NULL
。
- 返回值:如果等待成功,返回
0
;否则返回错误码。
示例代码
以下是一个简单的示例,演示了线程的创建、终止和等待:
注意事项
- 线程同步:在多线程程序中,需要使用互斥锁、条件变量等同步机制来避免线程间的竞态条件和死锁问题。
- 资源清理:线程终止时,需要确保其占用的资源(如内存、文件描述符等)得到正确释放,以避免资源泄露。
- 取消点:线程取消操作只在取消点处生效,取消点是一些系统调用和库函数,如
read
、write
、pthread_testcancel
等。
通过合理使用线程控制、创建、终止和等待等操作,可以有效地管理和协调多线程程序的执行,提高程序的并发性能和响应性。
cp问题
comsumer&producer问题就是“321”原则
三种关系:消费者vs消费者,消费者vs生产者,生产者vs生产者
两种角色:生产者,消费者
一个交易场所:某种结构的内存空间
优点:
1.支持忙闲不均
2.生产和消费进行解藕
为什么有锁了还需要信号量这个东西
锁和信号量都是用于多线程和多进程同步的重要机制,但它们在功能和使用场景上有所不同。虽然锁可以解决很多同步问题,信号量仍然有其独特的用途和优势。以下是锁和信号量的主要区别以及为什么需要信号量的详细解释:
锁和信号量的主要区别
1. 功能和用途
- 锁(互斥锁):
- 功能:锁主要用于互斥(Mutex),确保同一时间只有一个线程可以访问共享资源。
- 用途:适用于保护临界区,避免数据竞争和数据不一致性。
- 信号量:
- 功能:信号量是一种计数器,用于控制对共享资源的访问数量。
- 用途:不仅可以用于互斥,还可以用于同步线程,允许多个线程同时访问共享资源。
2. 实现机制
- 锁:
- 锁的实现相对简单,通常只允许一个线程进入临界区。
- 锁的加锁和解锁必须由同一线程分别对应使用。
- 信号量:
- 信号量通过计数器来控制资源的访问,计数器大于0时,表示有资源可用。
- 信号量的
wait
操作会减少计数器,signal
操作会增加计数器。 - 信号量可以由一个线程释放,另一个线程获取。
3. 灵活性和控制能力
- 锁:
- 锁提供了简单的互斥控制,适合保护临界区。
- 锁的使用相对简单,但可能导致死锁和饥饿。
- 信号量:
- 信号量提供了更灵活的控制,可以允许多个线程同时访问资源。
- 信号量可以用于复杂的同步模式,如生产者-消费者问题。
为什么需要信号量
- 允许多个线程访问资源:
- 锁通常只允许一个线程进入临界区,而信号量可以允许多个线程同时访问共享资源。
- 例如,在资源池(如数据库连接池)场景中,允许多个线程同时访问资源是必要的。
- 实现复杂的同步模式:
- 信号量可以用于实现复杂的同步模式,如生产者-消费者问题。
- 在生产者-消费者问题中,信号量可以控制缓冲区的满和空状态,确保生产者和消费者之间的同步。
- 非owner线程释放锁:
- 在某些特殊情况下,如死锁恢复,信号量允许非owner线程释放锁,而锁则做不到。
示例:生产者-消费者问题
假设有一个生产者和一个消费者,共享一个缓冲区。生产者生产数据放入缓冲区,消费者从缓冲区取出数据。这里需要两个信号量:
- empty:表示缓冲区空位的数量。
- full:表示缓冲区中有数据的数量。
c复制
sem_t empty;
sem_t full;
void producer() {
while (true) {
produce_item();
sem_wait(&empty); // 等待空位
insert_item();
sem_signal(&full); // 增加满位
}
}
void consumer() {
while (true) {
sem_wait(&full); // 等待数据
remove_item();
sem_signal(&empty); // 增加空位
consume_item();
}
}
总结
虽然锁和信号量都可以用于同步,但它们在功能和使用场景上有所不同。锁主要用于互斥,而信号量不仅可以用于互斥,还可以用于同步和控制资源的访问数量。在某些场景下,信号量提供了更灵活的控制和更复杂的同步模式,这是锁无法实现的。
基于环形队列的生产消费模型

head永远指向下一个要补充的位置,tail永远指向下一个要使用的位置
空和满的时候head和tail指向同一个位置,同时也就没有办法判断是空还是满

记住321原则;
- Author:PytC
- URL:https://PytC.fun//article/15949b4c-fd33-80e5-b7b5-d2fb49c7fc45
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!