线程同步与互斥---线程互斥
目录程线程间的互斥相关背景概念1.线程互斥1.见一种现象(数据不一致问题)2.解决这个问题(锁pthread锁)3.理解为什么数据会不一致认识加锁的接口4.理解锁线程是共享地址空间的---线程会共享大部分资源---那么在多线程访问这个共享资源时我们把共享资源叫做公共资源各种情况的数据不一致问题---解决这些问题同步和互斥程线程间的互斥相关背景概念• 共享资源• 临界资源多线程执行流被保护的共享的资源就叫做临界资源• 临界区每个线程内部访问临界资源的代码就叫做临界区• 互斥任何时刻互斥保证有且只有一个执行流进入临界区访问临界资源通常对临界资源起 保护作用• 原子性后面讨论如何实现不会被任何调度机制打断的操作该操作只有两态要么完成 要么未完成1.线程互斥1.见一种现象(数据不一致问题)TestMutex.cc// 操作共享变量会有问题的售票系统代码 #include stdio.h #include stdlib.h #include string.h #include unistd.h #include pthread.h int ticket 1000; void *route(void *arg) { char *id (char *)arg; while (1) { if (ticket 0) { usleep(1000); //模拟抢票花的时间 printf(%s sells ticket:%d\n, id, ticket); //抢到了票 ticket--; //票数-- } else { break; } } return nullptr; } int main(void) { pthread_t t1, t2, t3, t4; pthread_create(t1, NULL, route, (void *)thread 1); pthread_create(t2, NULL, route, (void *)thread 2); pthread_create(t3, NULL, route, (void *)thread 3); pthread_create(t4, NULL, route, (void *)thread 4); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_join(t3, NULL); pthread_join(t4, NULL); }MakefileTestMutex:TestMutex.cc g -o $ $^ -stdc11 -lpthread .PHONY:clean clean: rm -f TestMutexrootiZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-27/5.mutex# make g -o TestMutex TestMutex.cc -stdc11 -lpthread rootiZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-27/5.mutex# ./TestMutex thread 2 sells ticket:1000 thread 1 sells ticket:1000 thread 3 sells ticket:1000 thread 4 sells ticket:1000 thread 2 sells ticket:996 thread 1 sells ticket:995 thread 3 sells ticket:995 ....... thread 3 sells ticket:10 thread 4 sells ticket:9 thread 2 sells ticket:8 thread 1 sells ticket:7 thread 3 sells ticket:6 thread 4 sells ticket:5 thread 2 sells ticket:4 thread 1 sells ticket:3 thread 3 sells ticket:2 thread 4 sells ticket:1 thread 2 sells ticket:0 thread 1 sells ticket:-1 thread 3 sells ticket:-2抢票抢到负数要把临界区保护起来2.解决这个问题(锁pthread锁)pthread_mutex_init 初始化互斥锁NAMEpthread_mutex_destroy,pthread_mutex_init - destrobyand initialize a mutexSYNOPSIS#include pthread.hint pthread_mutex_destroy(pthread_mutex_t *mutex);int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER;pthread_mutex_lock//加锁pthread_mutex_unlock//解锁TestMutex.cc// 操作共享变量会有问题的售票系统代码 #include stdio.h #include stdlib.h #include string.h #include unistd.h #include pthread.h int ticket 1000; pthread_mutex_t lock PTHREAD_MUTEX_INITIALIZER; void *route(void *arg) { char *id (char *)arg; while (1) { pthread_mutex_lock(lock); if (ticket 0) // 1. 判断 { usleep(1000); // 模拟抢票花的时间 printf(%s sells ticket:%d\n, id, ticket); // 2. 抢到了票 ticket--; // 3. 票数-- pthread_mutex_unlock(lock); } else { pthread_mutex_unlock(lock); break; } } return nullptr; } int main(void) { pthread_t t1, t2, t3, t4; pthread_create(t1, NULL, route, (void *)thread 1); pthread_create(t2, NULL, route, (void *)thread 2); pthread_create(t3, NULL, route, (void *)thread 3); pthread_create(t4, NULL, route, (void *)thread 4); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_join(t3, NULL); pthread_join(t4, NULL); }被保护起来的共享资源叫做临界资源3.理解为什么数据会不一致认识加锁的接口多线程---抢票为什么会减到负数--不是主要矛盾但是和它有关1.ticket--不是原子的C语言-汇编语言暂时 当前一条汇编就是原子的3条汇编切换数据不一致问题CPU在执行执行流的代码1.内存把ticket值载入到CPU的ebx寄存器中2.CPU内做--3.减完写回内存更改pc指针是一个CPU寄存器存储下一条要执行的指令的内存地址票数为什么减到了负数if (ticket 0) ----也是一种计算逻辑计算---CPU判断1.载入2.判断是主要矛盾多个线程同时进入串行式--从而减到负数一个全局资源没有加保护可能会有并发问题---线程安全问题多线程中制造更多的并发更多的切换---切换的时间点是什么时候1.时间片 2.阻塞是IO 3.sleep等...(切走)陷入内核选择新的从内核态返回用户态的时候进行检查引入锁:pthread_mutex_t 互斥锁/互斥量#include pthread.hint pthread_mutex_destroy(pthread_mutex_t *mutex);//释放int pthread_mutex_init(pthread_mutex_t *restricct mutexconst pthread_mutexattr_t *restrict attr);//初始化全局pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER;全局锁不需要被释放程序运行结束会自动释放申请锁int pthread_mutex_lock(pthread_mutex_t *mutex);//加锁int pthread_mutex_trylock(pthread_mutex_t *mutex);//申请锁的非阻塞版本int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁加锁解锁都是原子的加锁要竞争申请锁多线程都得先看到锁锁本身就是临界资源申请锁的过程必须是原子的申请成功继续向后运行访问临界区代码访问临界资源失败阻塞挂起申请执行流|锁提供的能力的本质执行临界区代码由并行转换为串行(在我执行期间不会被打扰也是一种变相的原子性的表现)加速尽量加锁的范围粒度要比较细尽可能的不要包含太多的非临界区代码testMutex.cpp// 操作共享变量会有问题的售票系统代码 #include iostream #include string #include stdio.h #include stdlib.h #include string.h #include unistd.h #include pthread.h int ticket 1000; class ThreadData { public: ThreadData(const std::string n, pthread_mutex_t lock) : name(n), lockp(lock) { } ~ThreadData() {} std::string name; pthread_mutex_t *lockp; }; //加速尽量加锁的范围粒度要比较细尽可能的不要包含太多的非临界区代码 void *route(void *arg) { ThreadData *td static_castThreadData *(arg); while (1) { pthread_mutex_lock(td-lockp); //if这部分是临界区其他是非临界区保护临界区通过加速和解锁 if (ticket 0) { usleep(1000); printf(%s sells ticket:%d\n, td-name.c_str(), ticket); ticket--; pthread_mutex_unlock(td-lockp); } else { pthread_mutex_unlock(td-lockp); break; } } return nullptr; } int main(void) { pthread_mutex_t lock; pthread_mutex_init(lock,nullptr);//初始化锁 pthread_t t1, t2, t3, t4; ThreadData *td1 new ThreadData(thread 1,lock); pthread_create(t1, NULL, route, td1); ThreadData *td2 new ThreadData(thread 2,lock); pthread_create(t2, NULL, route, td2); ThreadData *td3 new ThreadData(thread 3,lock); pthread_create(t3, NULL, route, td3); ThreadData *td4 new ThreadData(thread 4,lock); pthread_create(t4, NULL, route, td4); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_join(t3, NULL); pthread_join(t4, NULL); pthread_mutex_destroy(lock);//销毁锁 return 0; }MakefiletestMutex:testMutex.cpp g -o $ $^ -stdc11 -lpthread .PHONY:clean clean: rm -f testMutexrootiZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-27.2# make g -o testMutex testMutex.cpp -stdc11 -lpthread rootiZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-27.2# ./testMutex thread 1 sells ticket:1000 thread 1 sells ticket:999 thread 1 sells ticket:998 thread 1 sells ticket:997 thread 1 sells ticket:996 ........ thread 3 sells ticket:4 thread 3 sells ticket:3 thread 3 sells ticket:2 thread 3 sells ticket:1全局的testMutex.cpp// 操作共享变量会有问题的售票系统代码 #include iostream #include string #include stdio.h #include stdlib.h #include string.h #include unistd.h #include pthread.h int ticket 1000; pthread_mutex_t glock PTHREAD_MUTEX_INITIALIZER;//全局的初始化 class ThreadData { public: ThreadData(const std::string n, pthread_mutex_t lock) : name(n), lockp(lock) { } ~ThreadData() {} std::string name; pthread_mutex_t *lockp; }; //加速尽量加锁的范围粒度要比较细尽可能的不要包含太多的非临界区代码 void *route(void *arg) { ThreadData *td static_castThreadData *(arg); while (1) { //pthread_mutex_lock(td-lockp); pthread_mutex_lock(glock); //if这部分是临界区其他是非临界区保护临界区通过加速和解锁 if (ticket 0) { usleep(1000); printf(%s sells ticket:%d\n, td-name.c_str(), ticket); ticket--; //pthread_mutex_unlock(td-lockp); pthread_mutex_unlock(glock); } else { //pthread_mutex_unlock(td-lockp); pthread_mutex_unlock(glock); break; } } return nullptr; } int main(void) { pthread_mutex_t lock; pthread_mutex_init(lock,nullptr);//初始化锁 pthread_t t1, t2, t3, t4; ThreadData *td1 new ThreadData(thread 1,lock); pthread_create(t1, NULL, route, td1); ThreadData *td2 new ThreadData(thread 2,lock); pthread_create(t2, NULL, route, td2); ThreadData *td3 new ThreadData(thread 3,lock); pthread_create(t3, NULL, route, td3); ThreadData *td4 new ThreadData(thread 4,lock); pthread_create(t4, NULL, route, td4); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_join(t3, NULL); pthread_join(t4, NULL); pthread_mutex_destroy(lock);//销毁锁 return 0; }MakefiletestMutex:testMutex.cpp g -o $ $^ -stdc11 -lpthread .PHONY:clean clean: rm -f testMutexrootiZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-27.3# make g -o testMutex testMutex.cpp -stdc11 -lpthread rootiZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-27.3# ./testMutex thread 1 sells ticket:1000 thread 1 sells ticket:999 thread 1 sells ticket:998 thread 1 sells ticket:997 thread 1 sells ticket:996 thread 1 sells ticket:995 ..... thread 1 sells ticket:5 thread 1 sells ticket:4 thread 1 sells ticket:3 thread 1 sells ticket:2 thread 1 sells ticket:1进程间互斥共享内存shm,(pthread_mutex_t*)shm我们有两个线程先创建一个共享内存。锁本质就是变量直接就用共享内存头部的位置让两个线程都能看到把头部位置强转成pthread_mutex_t*。就可以直接使用init初始化destroy做销毁。对临界资源进行保护本质其实就是用锁来对临界区代码进行保护问题1如果有一个线程不遵守你的规则---写bug---所有线程都必须遵守问题2加速之后在临界区内部允许线程切换吗切换了会怎么样--不怎么样所有线程必须等我跑完允许切换的---但是不担心因为我当前线程并没有释放锁我是持有锁被切换的即使我不在其他线程也得等我回来执行完代码释放锁其他线程才能展开锁的竞争进入临界区站在外边的人是如何看待你的自习过程呢要么不用要么用完对外边的人才有意义原子性你的自习对外边的人是原子的4.理解锁锁的原理1.硬件及实现关闭时钟中断2.软件级实现• 为了实现互斥锁操作,大多数体系结构都提供了swap或exchange指令,该指令的作用是把寄存器和 内存单元的数据相交换,由于只有一条指令,保证了原子性,即使是多处理器平台,访问内存的 总线周 期也有先后,一个处理器上的交换指令执行时另一个处理器的交换指令只能等待总线周期。锁本质上就是一个标志位理解锁的前提进程/线程切换CPU内的寄存器硬件只有一套但CPU寄存器内的数据可以有多份各自一份当前执行流的上下文|换句话说如果把一个变量的内容交换到CPU寄存器内部本质是把该变量的内容获取到当前执行流的上下文中|当前CPU寄存器的硬件上下文(其实就是各个寄存器的内容)属于进程/线程私有的|所以我们用swapexchange将内存中的变量交换到CPU的寄存器中本质是当前线程/进程,在获取锁因为是交换不是拷贝所以内部1只有一份所以谁申请到谁持有锁线程A/B进寄存器要把寄存器清零但是清的都是自己的上下文数据。彼此不会影响也不怕中断exchange无法被中断线程A被切走带走自己的%al:1谁交换成功谁就持有锁了Mutex就相当于这把锁谁持有这个1谁就持有锁所以释放锁/解锁的时候只要往Mutex写1就可以了C11也提供了std::mutex lock;#includemutextestMutex.cpp// 操作共享变量会有问题的售票系统代码 #include iostream #includemutex #include string #include stdio.h #include stdlib.h #include string.h #include unistd.h #include pthread.h int ticket 1000; pthread_mutex_t glock PTHREAD_MUTEX_INITIALIZER;//全局的初始化 std::mutex cpp_lock; class ThreadData { public: ThreadData(const std::string n, pthread_mutex_t lock) : name(n), lockp(lock) { } ~ThreadData() {} std::string name; pthread_mutex_t *lockp; }; //加速尽量加锁的范围粒度要比较细尽可能的不要包含太多的非临界区代码 void *route(void *arg) { ThreadData *td static_castThreadData *(arg); while (1) { cpp_lock.lock(); //pthread_mutex_lock(td-lockp); //pthread_mutex_lock(glock); //if这部分是临界区其他是非临界区保护临界区通过加速和解锁 if (ticket 0) { usleep(1000); printf(%s sells ticket:%d\n, td-name.c_str(), ticket); ticket--; //pthread_mutex_unlock(td-lockp); //pthread_mutex_unlock(glock); cpp_lock.unlock(); } else { //pthread_mutex_unlock(td-lockp); //pthread_mutex_unlock(glock); cpp_lock.unlock(); break; } } return nullptr; } int main(void) { pthread_mutex_t lock; pthread_mutex_init(lock,nullptr);//初始化锁 pthread_t t1, t2, t3, t4; ThreadData *td1 new ThreadData(thread 1,lock); pthread_create(t1, NULL, route, td1); ThreadData *td2 new ThreadData(thread 2,lock); pthread_create(t2, NULL, route, td2); ThreadData *td3 new ThreadData(thread 3,lock); pthread_create(t3, NULL, route, td3); ThreadData *td4 new ThreadData(thread 4,lock); pthread_create(t4, NULL, route, td4); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_join(t3, NULL); pthread_join(t4, NULL); pthread_mutex_destroy(lock);//销毁锁 return 0; }MakefiletestMutex:testMutex.cpp g -o $ $^ -stdc11 -lpthread .PHONY:clean clean: rm -f testMutexMutex.hpp#pragma once #include iostream #include pthread.h namespace MutexMudole { class Mutex { public: Mutex() { pthread_mutex_init(_mutex, nullptr); } void Lock() { int n pthread_mutex_lock(_mutex); (void)n; } void Unlock() { int n pthread_mutex_unlock(_mutex); (void)n; } ~Mutex() { pthread_mutex_destroy(_mutex); } private: pthread_mutex_t _mutex; }; }testMutex.cpp// 操作共享变量会有问题的售票系统代码 #include iostream #includemutex #include string #include stdio.h #include stdlib.h #include string.h #include unistd.h #include pthread.h #includeMutex.hpp using namespace MutexMudole; int ticket 1000; //pthread_mutex_t glock PTHREAD_MUTEX_INITIALIZER;//全局的初始化 //std::mutex cpp_lock; class ThreadData { public: ThreadData(const std::string n, Mutex lock) : name(n), lockp(lock) { } ~ThreadData() {} std::string name; Mutex *lockp; }; //加速尽量加锁的范围粒度要比较细尽可能的不要包含太多的非临界区代码 void *route(void *arg) { ThreadData *td static_castThreadData *(arg); while (1) { //cpp_lock.lock(); //pthread_mutex_lock(td-lockp); //pthread_mutex_lock(glock); //if这部分是临界区其他是非临界区保护临界区通过加速和解锁 td-lockp-Lock(); if (ticket 0) { usleep(1000); printf(%s sells ticket:%d\n, td-name.c_str(), ticket); ticket--; //pthread_mutex_unlock(td-lockp); //pthread_mutex_unlock(glock); //cpp_lock.unlock(); td-lockp-Unlock(); } else { //pthread_mutex_unlock(td-lockp); //pthread_mutex_unlock(glock); //cpp_lock.unlock(); td-lockp-Unlock(); break; } } return nullptr; } int main(void) { // pthread_mutex_t lock; // pthread_mutex_init(lock,nullptr);//初始化锁 Mutex lock; pthread_t t1, t2, t3, t4; ThreadData *td1 new ThreadData(thread 1,lock); pthread_create(t1, NULL, route, td1); ThreadData *td2 new ThreadData(thread 2,lock); pthread_create(t2, NULL, route, td2); ThreadData *td3 new ThreadData(thread 3,lock); pthread_create(t3, NULL, route, td3); ThreadData *td4 new ThreadData(thread 4,lock); pthread_create(t4, NULL, route, td4); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_join(t3, NULL); pthread_join(t4, NULL); //pthread_mutex_destroy(lock);//销毁锁 return 0; }MakefiletestMutex:testMutex.cpp g -o $ $^ -stdc11 -lpthread .PHONY:clean clean: rm -f testMutexrootiZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-27.4# make g -o testMutex testMutex.cpp -stdc11 -lpthread rootiZ5waahoxw3q2bZ:~/linux-learning/linux/26-6-27.4# ./testMutex thread 1 sells ticket:1000 thread 1 sells ticket:999 thread 1 sells ticket:998 thread 1 sells ticket:997 ..... thread 2 sells ticket:3 thread 2 sells ticket:2 thread 2 sells ticket:1RAII风格的互斥锁Mutex.hpp#pragma once #include iostream #include pthread.h namespace MutexMudole { class Mutex { public: Mutex() { pthread_mutex_init(_mutex, nullptr); } void Lock() { int n pthread_mutex_lock(_mutex); (void)n; } void Unlock() { int n pthread_mutex_unlock(_mutex); (void)n; } ~Mutex() { pthread_mutex_destroy(_mutex); } private: pthread_mutex_t _mutex; }; class LockGuard { public: LockGuard(Mutex mutex):_mutex(mutex) { _mutex.Lock(); } ~LockGuard() { _mutex.Unlock(); } private: Mutex _mutex; }; }testMutex.cpp// 操作共享变量会有问题的售票系统代码 #include iostream #include mutex #include string #include stdio.h #include stdlib.h #include string.h #include unistd.h #include pthread.h #include Mutex.hpp using namespace MutexMudole; int ticket 1000; class ThreadData { public: ThreadData(const std::string n, Mutex lock) : name(n), lockp(lock) { } ~ThreadData() {} std::string name; Mutex *lockp; }; // 加速尽量加锁的范围粒度要比较细尽可能的不要包含太多的非临界区代码 void *route(void *arg) { ThreadData *td static_castThreadData *(arg); while (1) { {//临界区 LockGuard guard(*td-lockp); // 加锁完成RAII风格的互斥锁的实现 if (ticket 0) { usleep(1000); printf(%s sells ticket:%d\n, td-name.c_str(), ticket); ticket--; } else { break; } } } return nullptr; } int main(void) { Mutex lock; pthread_t t1, t2, t3, t4; ThreadData *td1 new ThreadData(thread 1, lock); pthread_create(t1, NULL, route, td1); ThreadData *td2 new ThreadData(thread 2, lock); pthread_create(t2, NULL, route, td2); ThreadData *td3 new ThreadData(thread 3, lock); pthread_create(t3, NULL, route, td3); ThreadData *td4 new ThreadData(thread 4, lock); pthread_create(t4, NULL, route, td4); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_join(t3, NULL); pthread_join(t4, NULL); return 0; }MakefiletestMutex:testMutex.cpp g -o $ $^ -stdc11 -lpthread .PHONY:clean clean: rm -f testMutex//代码块进代码块开空间出代码块释放空间。所以两个不冲突不会重定义{int a10;}int a20;感谢你的观看期待我们下次再见

相关新闻

深入解析EDMA3控制器:事件与中断寄存器机制及实战应用

深入解析EDMA3控制器:事件与中断寄存器机制及实战应用

1. EDMA3控制器事件与中断机制概述在嵌入式系统,尤其是德州仪器(TI)的C6000系列DSP平台上,EDMA3控制器是数据搬移任务的核心引擎。它的价值在于将CPU从繁重的、重复性的数据搬运工作中彻底解放出来,让CPU能够专注于算法…

2026/9/14 9:14:24 阅读更多 →
Vim常用操作(编程常用)

Vim常用操作(编程常用)

Vim常用操作(编程常用)Vim 是 Linux 系统上最强大的文本编辑器之一,掌握它能极大提升编辑效率。本文整理了 Vim 最核心的操作,适合日常开发和快速查阅。一、三种模式 Vim 共有三种模式:命令模式(Normal)、编辑模式&…

2026/9/11 11:38:57 阅读更多 →
AI编程工具横向对比:7大维度(响应延迟、上下文长度、私有部署支持、API调用成本、调试辅助能力、多语言覆盖度、企业合规认证)深度测评,选错工具=每月多花27小时

AI编程工具横向对比:7大维度(响应延迟、上下文长度、私有部署支持、API调用成本、调试辅助能力、多语言覆盖度、企业合规认证)深度测评,选错工具=每月多花27小时

更多请点击: https://kaifayun.com 第一章:AI编程工具横向对比:7大维度深度测评总览 AI编程辅助工具正迅速重塑开发者工作流,但工具选择高度依赖具体场景与技术栈。本章基于实测数据,从代码生成质量、上下文理解深度、…

2026/9/10 16:24:28 阅读更多 →

最新新闻

文乃配置踩坑实录:3个致命错误教你新手避坑

文乃配置踩坑实录:3个致命错误教你新手避坑

文乃配置踩坑实录:3个致命错误教你新手避坑 配置环境就卡半天?别急,这真不是你的锅。很多新手在折腾 wenai 相关工具链或同名库时,常因版本冲突或路径问题陷入死循环,看似简单却处处是雷。 坑的现象:报错信息像天书,日志根本看不懂…

2026/9/22 3:14:53 阅读更多 →
lol一折高频面试题:3个坑让你少加班

lol一折高频面试题:3个坑让你少加班

lol一折高频面试题:3个坑让你少加班 面试被问原理答不上来,当场大脑空白?别慌,lol一折这类高频面试题,90%的人栽在细节里。我踩过的坑,现在全掏出来给你看。 坑的现象:代码能跑,上线就炸…

2026/9/22 3:14:53 阅读更多 →
ckg选型保姆级教程:3分钟看懂核心差异,拒绝文档焦虑

ckg选型保姆级教程:3分钟看懂核心差异,拒绝文档焦虑

ckg选型保姆级教程:3分钟看懂核心差异,拒绝文档焦虑 官方文档翻了三遍还是云里雾里?别急,很多开发者在接触 ckg 相关技术栈时,最大的痛点就是 资料分散且官方文档过于晦涩…

2026/9/22 3:14:53 阅读更多 →
5个核心考点:一文搞懂磁盘阵列恢复面试真题

5个核心考点:一文搞懂磁盘阵列恢复面试真题

5个核心考点:一文搞懂磁盘阵列恢复面试真题 面试被问磁盘阵列恢复逻辑卡壳?复制来的恢复代码跑不通,报错信息看不懂?别慌,这种“原理懂但手生”的困境,90%的运维和后端开发者都经历过。今天不玩虚的,直接拆解大厂高频面试题,带你一文搞懂磁盘阵列…

2026/9/22 3:14:53 阅读更多 →
代写assignment速查手册:3个坑让你面试翻车

代写assignment速查手册:3个坑让你面试翻车

代写assignment速查手册:3个坑让你面试翻车 面试官刚问完“讲讲你的项目难点”,你脑子里一片空白。 那种感觉像被抽走了灵魂,嘴巴张合却发不出声音。 别慌,这种“原理失忆”在Java后端面试中太常见了。…

2026/9/22 3:14:53 阅读更多 →
3天搞定博士夫妻相声后端架构:手写实现高并发接口

3天搞定博士夫妻相声后端架构:手写实现高并发接口

3天搞定博士夫妻相声后端架构:手写实现高并发接口 昨晚改代码改到凌晨两点,屏幕上一片红,StackTrace 长得像天书,报错信息全是 NullPointerException 和 OutOfMemoryError…

2026/9/22 3:13:53 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/21 3:13:20 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/21 2:19:36 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/22 2:43:42 阅读更多 →