8.21面试复盘

发布于:2024-08-24 ⋅ 阅读:(151) ⋅ 点赞:(0)

读写锁和互斥锁

1. 概念

互斥锁(Mutex)

  • 互斥锁是一种用于确保同一时间只有一个线程能够访问共享资源的同步机制。
  • 其基本作用是保护临界区,避免多个线程同时进入导致数据竞态和不一致性的问题。

读写锁(Read-Write Lock)

  • 读写锁允许多个线程同时读取共享资源,但在写操作时,必须独占资源。这种机制有助于提高多线程环境中对共享资源的访问效率。
  • 读写锁将线程的访问分为两种类型:读锁和写锁。读锁是共享的,多个线程可以同时持有读锁;而写锁是独占的,任何线程持有写锁时,其他线程不能持有读锁或写锁。

2. 使用场景

互斥锁

  • 适用于对资源的访问几乎总是写操作,或者读写操作的比例接近时。
  • 比如:保护某个写操作频繁的资源,或者不需要区分读写操作时。

读写锁

  • 适用于读操作远远多于写操作的场景。
  • 比如:数据结构的查询操作频繁而更新操作稀少时,如缓存系统。

3. 实现方式

互斥锁

  • 互斥锁通常通过标志位、原子操作或操作系统提供的锁机制来实现。
  • 比如,POSIX线程库中的pthread_mutex_t,Windows中的CRITICAL_SECTIONHANDLE

读写锁

  • 读写锁的实现比互斥锁要复杂。通常包括:

    • 计数器:用于跟踪当前持有读锁的线程数量。
    • 状态标志:指示是否有线程持有写锁。
    • 线程队列:用于管理等待读锁或写锁的线程。

    具体实现中:

    • 读锁通常会有一个计数器,允许多个线程同时获取读锁,只要没有线程持有写锁。
    • 写锁需要确保在写操作进行时,所有其他读锁和写锁都被释放,以确保数据一致性。

4. 性能差异

互斥锁

  • 由于互斥锁只允许一个线程访问临界区,因此在高竞争的情况下可能导致线程阻塞,降低并发性能。
  • 适用于线程访问共享资源的竞争较高,或没有显著的读写比例差异的情况。

读写锁

  • 当读操作远多于写操作时,读写锁可以显著提高性能。多个线程可以同时进行读操作,从而提高了系统的并发度。
  • 写操作会造成所有线程(读和写)阻塞,写锁的竞争会影响性能,因此需要在写操作的频率较低时使用读写锁。

GDB查看core文件

1.启动GDB并指定程序和core文件

gdb /path/to/your/program /path/to/corefile

 2.查看程序崩溃的位置

当 GDB 加载了 core 文件后,它通常会自动打印出程序崩溃的位置,并显示调用栈(backtrace)。btbacktrace 的简写,显示当前调用栈的详细信息,包括函数调用、源文件和行号。

3.检查程序状态

查看崩溃时的线程信息:

info threads

 切换到特定线程(如果有多个线程):

thread <thread-number>

 打印线程的调用栈:

bt

4.查看变量值

查看崩溃位置附近的变量值:

frame

 打印当前帧的局部变量

print <variable-name>

linux命令

find

按文件名查找

find /path/to/search -name "filename"

按文件大小查找:查找大于100M的

find /path/to/search -size +100M

按文件类型查找

find /path/to/search -type f
只查找文件
find /path/to/search -type d
只查找目录

vi修改文件格式

1.打开文件

vi filename

2.进入命令模式:如果在插入模式(可以输入文字),按 Esc 键返回命令模式。

设置为 Unix 格式::set fileformat=unix

设置为 DOS 格式::set fileformat=dos

3.保存退出:

:wq

将 .so 动态库编译到程序中

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
./myprogram
  • -L. 指定当前目录为库搜索路径。
  • -lmylib 表示链接名为 libmylib.so 的库。

join和detach

1. join

  • 阻塞调用:当一个线程调用 join 时,调用线程会阻塞,直到被 join 的线程结束。
  • 获取返回值:可以获取被 join 的线程的返回值。
  • 资源清理:确保线程资源被正确清理,防止内存泄漏。
  • 使用场景:当需要等待某个线程完成并获取其结果时使用。

2. detach

  • 非阻塞调用:调用 detach 后,线程将独立于调用线程运行。调用线程不会等待它完成。
  • 无法获取返回值:无法获取被 detach 的线程的返回值。
  • 资源管理:线程在结束后会自动释放资源,但程序不能通过 join 来显式地清理。
  • 使用场景:当线程的生命周期不需要与主线程同步或者不需要获取结果时使用。

条件变量和信号量

条件变量和信号量是多线程编程中常用的同步机制,它们有一些关键的区别:

条件变量

  1. 用途

    • 用于线程之间的等待和通知。
    • 线程可以等待某个条件变量,而另外的线程可以通知(或广播)这个条件发生了变化。
  2. 使用方式

    • 通常与一个互斥锁(mutex)配合使用。
    • 线程在等待条件变量时会释放关联的互斥锁,等待被通知后重新获得锁。
  3. 特性

    • 适用于需要等待特定条件的情况。
    • 支持广播通知(唤醒所有等待线程)。

信号量

  1. 用途

    • 用于计数资源或控制对共享资源的访问。
    • 可以有一个计数值,用于表示可用资源的数量。
  2. 使用方式

    • 通过增加或减少计数器来实现同步。
    • 线程等待信号量时会阻塞,直到信号量计数器大于零。
  3. 特性

    • 分为二进制信号量(类似互斥锁)和计数信号量。
    • 不需要与互斥锁一起使用。
    • 适用于控制资源访问和管理并发线程数。

总结

  • 条件变量适合于线程需要等待条件满足的场景。
  • 信号量适合于资源管理和控制并发访问的场景。