Linux线程3.0-线程同步与互斥,C/C++互斥锁。

发布时间:2026/6/24 5:25:39

Linux线程3.0-线程同步与互斥,C/C++互斥锁。 bit::Shadow✧(≖ ◡ ≖✿目录原子 / 非原子原子操作对信号怎么处理非原子操作的矛盾互斥锁解决的问题锁的本质接口定义锁全局定义局部定义释放加锁、解锁为什么加锁解锁都是原子的呢加锁之后临界区内线程切换会怎么样多线程模拟并发视频演示无锁将票抢到负数视频演示有锁正常抢票互斥锁的理解执行流程C下的锁互斥锁RAII锁最常用的锁99%原子 / 非原子以 a-- 为例探究原子与非原子。原子操作的本质给CPU发出指令对于“a”的修改不允许任何外部事件打断也不允许被其他核心看到中间状态。原子操作对信号怎么处理以原子操作为优先信号先被挂起。// kill -9 [pid]等硬核信号除外。非原子操作的矛盾以a--为例读取LoadCPU 将a的值3从主内存加载到它内部的寄存器如eax中。修改ModifyCPU 在寄存器中执行eax eax - 1此时eax的值变为 2。写入StoreCPU 将寄存器中的新值2写回主内存中a所在的内存地址。在以上非原子操作中若出现并发问题那么执行流就可能发生混乱而造成预料之外的结果。解决方法——创建互斥锁来限制线程的并发互斥锁解决的问题轻量级进程间信息过于同步而导致同时访问的问题。多线程下临界区内非原子性操作带来的执行流内指令重置混乱的问题。锁的本质☆互斥锁lock()的本质是将原先并行的轻量级进程改为串行。接口pthread_mutex_tpPOSIXportable Operating Systemd interface可移植操作系统接口。mutexmutual exclusion互斥。ttype类型。定义锁锁既需要定义还需要释放全局定义互斥锁在全局进行定义初始化pthread_mutex_t mutex PTHREAD_MUTEX_INITLIZER;局部定义必须使用pthread_mutex_init()pthread_mutex_t mutex; int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr);*mutex锁。*attr锁的属性nullptr即可。释放int pthread_mutex_destroy(pthread_mutex_t* mutex);加锁、解锁不论加锁还是解锁均是原子的phtread_mutex_lock(pthread_mutex_t* mutex); phtread_mutex_unlock(pthread_mutex_t* mutex);加锁失败会阻塞挂起执行流。为什么加锁解锁都是原子的呢“上锁”的目的就是“保证锁内区域所有操作均是‘原子’的”而只有持锁线程完毕才能“放下锁”——下一线程持锁进入锁区。若加锁不是原子的那么也就导致了“持锁时并发混乱问题”。加锁之后临界区内线程切换会怎么样线程主导更换但持锁线程不变。多线程模拟并发3个线程同时抢票#includeunistd.h #includeiostream #includepthread.h static int ticket 10000; void* routine(void* arg) { while (ticket) { //等待一会儿确保多个线程进来 usleep(500);//500ms printf(%d\n, --ticket); } return arg; } int main() { //3个新线程抢1000票 pthread_t pd1,pd2,pd3; pthread_create(pd1, nullptr, routine, (void*)pthread_1); pthread_create(pd2, nullptr, routine, (void*)pthread_2); pthread_create(pd3, nullptr, routine, (void*)pthread_3); pthread_join(pd1, nullptr); pthread_join(pd2, nullptr); pthread_join(pd3, nullptr); return 0; }视频演示无锁将票抢到负数无锁多线程抢票发现循环一直进行不会终止。原因分析while(ticket)仅当0时判断为假usleep(500)下足够线程进入循环内会将票数直接减为负数后再出循环判断。在原子操作区加互斥锁即可static int ticket 500; pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER; void* routine(void* arg) { while (ticket) { pthread_mutex_lock(mutex); if(ticket 0) { //先前线程已然将票抢完 这些线程就解锁并退出 pthread_mutex_unlock(mutex); break; } //等待一会儿确保多个线程进来 usleep(1000);//500ms printf(%d\n, --ticket); if(ticket 0) pthread_mutex_unlock(mutex); pthread_mutex_unlock(mutex);// ticket0解锁其他线程进来 } return arg; }视频演示有锁正常抢票加锁抢票互斥锁的理解锁限制了“原子性”标志的掌握者下图中%al是寄存器的一种。执行流程1.将寄存器内数据置零。2.交换寄存器内数据与内存。3.根据持锁(内存中的1标志)情况决定线程行为。C下的锁互斥锁最基础的独占锁只有一个线程可以占用。//定义 std::mutex mutex; //加锁、解锁 mutex.lock(); mutex.unlock();RAII锁最常用的锁99%⚛️使用RAII原则“资源获取即初始化”构造时自动加锁出作用域自动解锁。本质是封装以上述C接口的类以调用相应的构造函数、析构函数std::lock_guardstd::mutex(mtx);由于lock_guard是作用域相关所以常常需要{}来限定。感谢支持持续更新欢迎关注

相关新闻