Lecture 8: Concurrency 1

从Oracle迁移数据到Hadoop 目标:把Oracle 下的数据文件迁移到 Hadoop , 数据表都是上亿条,每个数据表的空间都超过100G。 关键是建立数据文件是UTF8格式,这样数据中的汉字在Hadoop 里显示才正常。 平台:CentOS 6.10 工具:Python 2.7 cx_Oracle 库 Oracle10.2.0.4.0 Hadoop 2.7.2-transwarp-5.2.1 1. 查看表... 阅读详情

线程和进程并发(concurrently)或并行执行(in parallel),并且可以共享资源(例如,设备、内存变量和数据结构)。

  • 多编程/多处理提高了系统利用率

线程可以在任何时间点(计时器、I/O)被中断。

  • 进程状态保存在进程控制块(process control block)中

项目的结果可能变得不可预测:

  • 共享数据可能会导致不一致——我们可能会在做某事的过程中被打断。
  • 执行的结果可能取决于代码在CPU上运行的顺序。

例子

递增计数器

#include <stdio.h>
#include <pthread.h>

int counter = 0;
void* calc(void* param) {
  int const iterations = 50000000;
  for(int i = 0; i < iterations; i++)
    counter++;
  return 0;
}

int main() {
  pthread_t tid1 = 0,tid2 = 0;
  pthread_create(&tid1, NULL, calc, 0);
  pthread_create(&tid2, NULL, calc, 0);
  pthread_join(tid1,NULL);
  pthread_join(tid2,NULL);
  printf("The value of counter is: %d\n", counter);
}

这段 C 程序是一个典型的 多线程竞态条件(Race Condition)示例,它创建了两个线程同时对同一个全局变量 counter 进行累加操作,最终打印 counter 的值。

  1. #include <stdio.h>
    #include <pthread.h>

    引入标准输入输出库和 POSIX 线程库(pthread)。

  2. int counter = 0;

    全局变量 counter,初始值为 0,两个线程都会访问并修改它。

  3. 线程函数:

    void* calc(void* param) {
        int const iterations = 50000000;
        for(int i = 0; i < iterations; i++)
            counter++;
        return 0;
    }

    每个线程都会执行这个函数。

    每个线程将 counter 自增 50,000,000 次。

  4. 主函数:

    int main() {
        pthread_t tid1 = 0, tid2 = 0;
        pthread_create(&tid1, NULL, calc, 0);
        pthread_create(&tid2, NULL, calc, 0);
        pthread_join(tid1, NULL);
        pthread_join(tid2, NULL);
        printf("The value of counter is: %d\n", counter);
    }

    创建两个线程 tid1 和 tid2,都执行 calc。

    pthread_join 等待两个线程执行完毕。

    打印 counter 的值。

Counter ++不是原子(“atomic”)操作,而是由三个独立的动作组成:

  • read: 从内存中读取计数器的值并将其存储在寄存器中
  • add: 对寄存器中的值加1
  • store: 将寄存器的值存储在内存中的计数器中

示例:

共享程序

考虑以下线程/进程之间共享的代码

chin 和 chout共享全局变量

void print()
{
  chin = getchar();
  chout = chin;
  putchar(chout);
}

考虑两个进程/线程和以下交错的指令序列(它们不相互作用):

考虑两个进程/线程和以下交错的指令序列(它们确实相互作用):

有界缓冲区

考虑一个有界缓冲区,其中可以存储N个项目

维护一个计数器来计算当前缓冲区中的项数

  • 添加项时递增
  • 删除项时自减

当多个线程读写有界缓冲区时,也会出现与计算总和类似的并发性问题。

生产者/消费者:用 counter 记录当前缓冲区中的数据项数。

// producer
while (true) {
  while (counter == BUFFER SIZE);
  buffer[in] = new_item;
  in = (in + 1) % BUFFER_SIZE;
  counter++;
}

// consumer
while (true) {
  while (counter == 0);
  consumed = buffer[out];
  out = (out + 1) % BUFFER_SIZE;
  counter--;
}

但它有两个关键缺陷:

  1. 竞态条件(Race Condition)
    生产者和消费者是两个线程,counter、in、out、buffer[] 都是共享变量,而所有读写操作都没有加任何同步原语(锁、信号量等)。
    例如:

    • 两个线程同时修改 counter;

    • 一个线程在读 buffer[out] 的同时,另一个线程可能正在写 buffer[in],甚至 in == out 时造成数据覆盖或读取脏数据。

  2. 忙等(Busy-waiting)
    while (counter == BUFFER_SIZE); 和 while (counter == 0); 属于轮询方式,会 100 % 占用 CPU,浪费资源。

竞态条件(Race Conditions)

如果代码的行为依赖于执行计算的时间,则代码具有竞态条件。

当多个线程访问共享数据时,通常会出现竞争条件,并且结果依赖于指令交错的顺序。

我们将对提供同步访问数据和避免竞争条件的机制感兴趣。

操作系统中的并发性

数据结构

现在的核心程序是抢占式的

  • 内核中正在运行多个线程。
  • 内核代码可以在任何时候被中断。

内核维护数据结构,如进程表和打开文件列表:

  • 这些数据结构可以并发访问。
  • 这可能会受到并发性问题的影响。

操作系统必须确保操作系统内部的交互不会导致竞争条件。

临界区和互斥

由于竞态条件可能导致疯狂的、不可预测的和明显的错误行为,我们希望软件抽象能够帮助防止它们。
临界区(critical section)是一段一次只能由一个线程运行的代码。这种性质被称为互斥(mutual exclusion)。

临界区

在编程中访问共享资源的一段代码,这段代码不能同时被多个执行线程访问。

互斥

在计算机科学中,指一种同一时间只允许一个进程或线程访问共享资源的机制。

那么问题就变成了如何执行互斥?潜在的方案:

  • O/S和编译器可以将临界区作为程序设计基本指令提供直接支持。
  • O/S和编译器提供的锁一次最多只能由一个线程持有。

互斥

do {
  ...
    // ENTRY to critical section
    critical section, e.g.counter++;
  // EXIT critical section
  // remaining code
    ...
} while (...);

临界区问题的解应满足以下要求:

  • 互斥:在任何一个时间点,只有一个进程处于临界段
  • 进程:任何进程都必须能够在某个时间点进入其临界区域。“剩余代码”中的进程/线程不会影响对临界区的访问
  • 公平/有限等待:公平分配的等待时间/进程不能无限期地等待

这些要求必须得到满足,与计算执行的顺序无关

强制互斥

强制互斥的标准方法是通过称为互斥锁(mutexes)的锁。这些可以通过各种方式实现:

  • 基于软件:Peterson的解决方案
  • 基于硬件:test_and_set(), swap_and_compare()
  • 基于O/S的——操作系统阻塞等待锁的进程。

不幸的是,互斥锁和其他并发原语(如信号量(semaphore))引入了一个新问题——死锁(deadlocks)。

死锁

例子

假设X和Y是互斥体(mutexes)。
线程A和线程B需要同时获取互斥锁,并以相反的顺序请求它们。
以下一系列事件可能发生在多程序系统中:

定义

如果一组线程中的每个线程都在等待只有该组中的另一个线程才能引起的事件,则该组线程被死锁

  • 每个死锁线程都在等待另一个死锁线程持有的资源(该线程不能运行,因此不能释放资源)。
  • 这可以发生在任意数量的线程之间和任意数量的资源上
最小条件

发生死锁必须满足四个条件:

  1. 互斥:一个资源一次最多只能分配给一个进程
  2. 保持和等待条件:资源可以在请求新资源时被保持
  3. 无抢占:不能从进程中强制拿走资源
  4. 循环等待:存在一个由两个或多个进程组成的循环链,等待其他进程持有的资源

如果不满足其中一个条件,则不会发生死锁

如果您的课程作业解决方案出现死锁,请检查请求资源的顺序

理解

1. x != y 会不会“原子地”发生?

不会。
即使表达式本身“只读”,它也要先把 x 和 y 的值从内存读到寄存器,再比较。
在大多数 ISA 上,这至少是两到三条指令:

load r1, [x]   ; 读 x
load r2, [y]   ; 读 y
cmp  r1, r2    ; 比较

如果另一个线程在这两条 load 之间把其中某个变量改掉,比较结果就可能“过时”。
因此读操作也需要同步(加锁、原子变量或 memory barrier)才能保证一致性。

2. 在“单硬件线程”的机器上会不会出现竞态或死锁?

  • 竞态条件
    如果操作系统做时间片抢占式调度,即使只有一个物理核,两个线程仍会在不同时间片里交替运行,因此竞态条件依旧可能触发。

  • 死锁
    死锁只需要“占有且等待”的四条件成立,与 CPU 个数无关。
    因此单核也能死锁——典型场景:线程 A 占锁 L1 后阻塞,线程 B 占锁 L2 后想去拿 L1,于是互相等待。

3. 两个线程跑同一个函数会不会互相死锁?

可能,也可能不会,关键在于函数里如何申请锁。

  1. 如果函数内部只用一把递归锁(或根本没锁),当然不会死锁。

  2. 如果函数内部按固定顺序先后拿两把锁,也不会死锁。

  3. 如果函数内部按不同顺序拿锁(例如线程 1:先 L1 后 L2,线程 2:先 L2 后 L1),就可能形成循环等待,从而死锁。

因此,“函数相同”本身不会阻止死锁;真正决定是否死锁的是锁的获取顺序和策略。

基于STM32避障/循迹/蓝牙遥控小车的硬件与软件底层设计 1、实现2m的自动直线行驶,要求左右偏移不大于10cm。2、车载显示屏显示车辆当前行驶速度或车辆运行时间,当前方20cm内出现障碍物时显示与前方障碍物的距离,车每次转弯蜂鸣器报警,同时通过左右指示灯指示转弯方向。3、依次驶过障碍物①②③④,且不触碰障碍物。4、成功进行调头转弯,行驶过程中车轮不碾压黑实线。5、在车道指定位置停车且不越界。6、通过红外、蓝牙、WiFi等任意一种方式实现对小车的控制,使其前进、后退、左转、右转。 阅读详情

相关推荐

动态库加载失败终极指南:从libbz2.so.1错误看Linux依赖管理本质

本文以经典的libbz2.so.1加载错误为例,深入剖析Linux动态链接库管理的核心机制。文章不仅提供从ldd检查、符号链接创建到LD_LIBRARY_PATH设置等实战解决方案,更系统性地讲解了动态链接器的寻库路径、版本管理及依赖问题预防策略,帮助开发者从根本上理解和掌握Linux依赖管理本质。

weixin_29212429的博客 447

[Stanford CS107] 个人笔记 Lecture 1

Lecture 1 What is Unix a set of standards and tools commonly used in software development. Command-line cd ls mkdir emacs rm man C Programming /* * hello.c * This program prints a welcome message ...

lvyin_33的博客 393

JLink版本不兼容?手把手教你解决APM32F003F6P6在Keil中烧写闪退和报错

本文详细解析了APM32F003F6P6在Keil中烧写闪退和报错的解决方案,重点介绍了JLink版本兼容性问题。通过实测不同版本组合,推荐使用JLink 7.20a或6.86b与Keil 5.25的黄金组合,并提供详细的降级驱动和工程配置步骤,帮助开发者高效解决烧写困境。

weixin_33694620的博客 416

周同学文章汇总

博主文章汇总

周同学的博客 1万+

微信DAT图片恢复全攻略:从文件定位到批量解密(附最新路径变化)

本文提供了一份详尽的微信DAT图片恢复指南,涵盖新旧版本文件路径变化解析、DAT文件定位方法以及批量解密操作步骤。针对微信图片加密存储为DAT格式的痛点,文章介绍了高效易用的图形化解密工具,帮助用户将加密文件快速还原为JPG、PNG等可查看格式,并强调了数据安全与隐私保护的重要性。

p4q5r6s7t的博客 743

【EMC电磁兼容】02.04——原理图的实战落地细节

原理图上的关于EMC的落地体现一、元器件的选型二、原理图上的EMC体现在哪里?1.芯片电源管脚滤波去耦:2.时钟电路滤波设计3.低速电路滤波抗干扰设计4.通讯接口电路的防护滤波5.系统输入电源端口电路的防护滤波6.系统接地的定义7.芯片软件功能的审查 一、元器件的选型 ​ 原理图最初设计涉及到选型元器件方面: 元器件选型 不仅仅功能需要满足要求,还需要考虑其它细节参数在不同应力下的反应,封装的不同也会产生不同的变化。 元器件替代 常常因为成本原因进行器件替代,除了要考虑功能参数相同时也要考虑系统参数

Time to Forget 2243

mit 6.824 Distributed System

文章目录LEC1 IntroductionLEC2 RPC and ThreadsLEC3 GFSLEC4 Primary-Backup ReplicationLEC5 Go, Threads, and RaftLEC6 Fault ToleranceLEC7 Fault Tolerance: Raft(2)LEC8 ZookeeperLEC9 More Replication, CRAQLEC10 Cloud Replicated DB, AuroraLEC11 Cache Consistency: Fr

283

android广告SDK原理详解(附源码)

广大的开发者吃糠咽菜开发了一两款APP,获取了一些流量后自然就会想到流量变现,一般情况下大家会选择到百度联盟或者Google Admob这些广告服务提供商注册开发者账号,在自己的APP里面加上几行广告位代码,集成他们的广告SDK包。然后谋事在人,成事在天,只有每天看报表查查收益。   也有一些开发者为了能够提高自己的变现水平,同时接入了好几家的sdk,哪家出的收益高一点我就出哪家的广告,但是这

rmcgogo的博客 1万+

基于Springboot+Vue的考研学习交流系统的设计与实现-计算机毕设 【课程设计】 22731

(1)首页:展示平台核心功能和最新动态,提供便捷的导航,个性化推荐帮助学生快速找到所需学习资源和活动信息。 (2)问答社区:学生可以提出问题、回答他人问题、分享经验,促进互动与知识共享,增强学习社群氛围。 (3)公告资讯:发布考研相关的公告、政策更新及重要通知,确保学生能够及时获得关于考试、报名等关键信息。 (4)留言反馈:学生可以提交问题或建议,平台会及时回应和处理反馈,提升用户体验并改进服务。 (5)免费视频与付费视频:平台提供免费的学习视频内容,并且支持购买付费视频课程,满足不同学习需求。 (6)考研

WeiXin_DZbishe的博客 1362

Debezium报错处理系列之二十一:Unable to connect: Communications link failure.The driver has not received any

Debezium报错系列之二十一:Unable to connect: Communications link failure.The driver has not received any。

zhengzaifeidelushang的博客 547

路径规划 | 详解混合A*算法Hybrid A*(附ROS C++/Python/Matlab仿真)

Hybrid A*算法通过结合连续状态空间搜索、运动约束考虑和轨迹优化等技术,弥补了普通A*算法在高维连续空间和的不足,提高了路径规划的效率和鲁棒性,广泛应用于车规级路径规划。本文详细图解Hybrid A*算法的原理——启发式、维诺耗散项、节点扩展法则等,并给出ROS C++、python、matlab三种语言的仿真实现加深理解

FRIGIDWINTER的博客 1万+

编译器 | 从工业实现到极简设计 —— 编译器的多元形态与实践

……

u013669912的博客 888

Test软件:Keysight二次开发_(3).安装与配置开发环境

在开始进行Keysight软件的二次开发之前,首先需要确保您的开发环境已经正确安装和配置。本节将详细介绍如何安装和配置必要的开发工具和依赖项,以便您能够顺利进行开发工作。

2401_87715305的博客 1413

鸿蒙操作系统实现应用接续跨设备流转实战

应用接续的落地成本很低:一个配置、一个onContinue回调、一处 launchReason 判断,合计不足百行代码,就能让任务在手机、平板、鸿蒙电脑之间无缝续接。随着互助通信共享等组网能力在更多机型下放,这条能力的实用价值会持续放大,建议交互密集型应用尽早接入。

NJPJI_Yang的博客 357

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

【Linux】APT 本地 deb 安装与 `-f` 参数总结笔记

apt install ./xx.deb 可自动解析并安装依赖,无需 -f;-f 仅用于修复已损坏的依赖状态,非首次安装时必需。apt install -f 可单独运行,修复 broken dependencies。两者职责不同:前者是安装与依赖解决,后者是故障修复。完全离线时需提前准备依赖包或本地源。

hknaruto的专栏 211

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

【Linux网络】TCP 服务器并发处理多客户端:从 fork 分发到双重 fork 彻底消灭僵尸进程

拆解 TCP 服务器并发演进链:fork 分发连接、SIGCHLD 循环回收僵尸、双重 fork 交孙进程给 init 收养,并给出模型选型与线上排错对照。

2301_78967866的博客 421

Linux rm 误删文件恢复实操教程

Linux使用rm删除文件时,并不会直接抹除磁盘上的数据,只是移除文件索引,让系统不再识别这块空间。只要没有写入新数据,原有扇区内容就会保留。新文件写入才有可能覆盖这些区域,一旦覆盖就很难找回。恢复的本质就是扫描磁盘,找到这些还存在、但索引丢失的数据条目,再把它们导出保存到其他分区。越早停止写入,恢复成功的概率越高。

海天数据恢复-winhex数据恢复教程 228

Linux sudo

如果输出 → 无 sudo 权限 如果输出 → 拥有全部 sudo 权限 辅助验证命令 ⚠️ 注意:在 wheel 组 ≠ 一定能 sudo,必须 开启 Ubuntu/Debian: ✅ 重要:修改组之后,用户要重新登录才生效! 或者执行 临时生效 看到这行(没有 #注释)才生效: 方式 2:visudo 直接单独给用户授权(精细化权限) 找到 ,下面添加一行: 自带语法校验,写错会告警,不要直接 vim 改 ,写错直接 sudo 炸掉! 想免密 su

fengliyang_的博客 178

【HarmonyOS 7 语音 AI 开放能力深度实战】 05 文本转语音实战,文字播报与合成状态控制

会议笔记已经整理成文字,用户离开屏幕以后,可能仍然希望听一遍已经确认的事项。应用可以提供一个播报按钮,把当前内容交给语音合成服务。但是,按钮点击成功与整段内容播放结束之间,还隔着引擎初始化、音色选择、合成和音频输出。页面如果在第一个完成回调出现时就恢复空闲,用户可能再次启动播报,让新的内容与尚未结束的声音互相影响。文本转语音服务负责把文字转换为声音,应用仍然需要选择音色、提交请求并管理页面状态。对于直接播报,合成引擎可以负责播放,页面不必另建播放器;但页面仍需要根据播放事件判断什么时候可以开始下一次操作。

Code Metaverse 181

ARM64-GNU汇编器

o伪指令分配大小例子伪指令分配大小例子.byte1 字节.byte 0x412 字节.word / .long 4 字节8 字节.ascii字符串(不加 \0)字符串(自动加 \0).byte:把 8位数当成数据插入汇编代码中。.hword和 .short:把16 位数当成数据插入汇编代码中。.long和 .int:这两个伪指令的作用相同,都把 32位数当成数据插入汇编代码中。.word:把 32位数当成数据插入汇编代码中。

weixin_43903002的博客 191

第一章 Shell 概述

本文介绍了Shell编程的基础知识,包括Shell的起源与发展、常见Shell类型及查看方式,阐述了Shell作为命令解释器连接用户与操作系统内核的作用。强调其作为解释型脚本语言的优势,适用于系统管理自动化任务。内容涵盖Shell脚本基本结构、注释规范、编写风格、执行方法及常用命令(如echo、printf、history、管道等),并讲解了命令执行顺序、退出状态码等核心概念,为初学者提供系统学习路径。

sbjdhjd的博客 275

Linux基本使用和程序部署

Linux是一个操作系统,和Windows是并列的关系。

LYYstudying的博客 84

二进制木马免杀-Python 分离免杀与 Web 挂马

二进制木马免杀-Python 分离免杀与 Web 挂马

2503_94637398的博客 268

鸿蒙沉浸光感开发适配

设备材质档位:EXQUISITE(精致,全光效,高性能设备)、GENTLE(均衡,默认)、SMOOTH(轻量,仅基础效果,低算力设备)、ADAPTIVE(自适应,系统自动识别算力选档,业务首选);用户系统设置三档(强/均衡默认/弱):本质是对透明度、反色率、折射强度的精细调控。用户的三档偏好由系统底层自动映射到渲染参数,应用只需一次定义材质,界面就会随用户设置平滑过渡,完全不需要针对三档分别写适配。

qq_63223749的博客 410

Windows 10/11 彻底禁用更新防止反弹完全指南:设置、服务、任务计划与批处理实战

Windows 10已于2025年10月14日终止支持,本文以22H2版本为例,系统性介绍通过设置、组策略、注册表、服务禁用及任务计划管理等多层手段彻底关闭自动更新。操作需管理员权限,可有效避免强制重启、节省资源并阻止Win11推送,但需手动处理安全补丁。文末提供完整批处理脚本与调试检查方法,实现一键禁用与验证。

seahahacsdn的博客 231

Linux篇(五)

本文系统梳理了Linux常用终端快捷键、软件包管理(yum/apt)、服务管理(systemctl)、软链接(ln)、时间与IP配置、域名解析、固定IP设置及网络命令(ping/wget/curl),涵盖日常运维核心操作,助力高效管理Linux环境。

wykyzdq的博客 188

Linux网络编程:TCP多线程远程命令执行与线程池改造

前面已经实现了 TCP Echo Server,并且通过多进程和多线程解决了多个客户端连接的问题。不过目前服务器的业务还是比较简单,客户端发送什么,服务器就返回什么。这次在原来的多线程服务器上继续做一些改动,实现一个简单的远程命令执行功能。这次主要学习了两个内容。第一个是多线程远程命令执行。通过 Command 类封装命令的接收、检查、执行和结果返回,并使用 set 对允许执行的命令进行限制。第二个是线程池版本的 TCP Echo Server。通过和std::bind。

2501_93388101的博客 360
上一篇: Lecture 7: Processes 4, Further Scheduling
下一篇: Lecture 9: Concurrency 2
Dead_Simba
博客等级 码龄2年 172粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值