guyeuro
V2EX  ›  问与答

单核并发是不是不会产生"线程不安全”的问题?

  •  
  •   guyeuro · Jun 26, 2017 · 9056 views
    This topic created in 3420 days ago, the information mentioned may be changed or developed.

    单核下 一个 CPU 核执行并发,在微观上来看还是串行的 这样是不是不会导致”线程不安全“? 只有多核并发才会导致线程不安全?

    40 replies  •  2017-06-27 15:35:26 +08:00
    mokeyjay
    mokeyjay
    Jun 26, 2017 via Android❤️4
    1
    …你是不是没有搞懂线程和并发的区别?
    guyeuro
    guyeuro
    OP
    Jun 26, 2017
    2
    @mokeyjay 哪里没有搞懂?
    bazingaterry
    bazingaterry
    Jun 26, 2017 via iPhone
    3
    锁这玩意,可比多核 CPU 早设计出来...
    hjc4869
    hjc4869
    Jun 26, 2017 via Android
    4
    会,你的非线程安全的代码执行了一半,这时一个时钟中断信号来了,切到别的线程去了,然后另一个线程就把你这个线程用的变量破坏了
    clearbug
    clearbug
    Jun 26, 2017 via Android
    5
    啥是并发?
    啥是并行?
    啥是线程安全?
    楼下来解释
    zwzmzd
    zwzmzd
    Jun 26, 2017 via iPhone
    6
    单核异步?所有代码块都是先后执行的,不存在同时执行两个代码块的问题,块内不用考虑线程安全问题。

    但实际中,为了性能考虑代码块的粒度都会尽量的小,还是会碰到相似问题
    zwzmzd
    zwzmzd
    Jun 26, 2017 via iPhone
    7
    @zwzmzd 发现看错题意了。
    即使单 cpu,操作系统也会按时间分片模拟出多核并发的效果,所以假设是不成立的
    maxxxxx
    maxxxxx
    Jun 26, 2017 via iPhone
    8
    实际上很多下游开发者是没有多核概念的。
    Lonely
    Lonely
    Jun 26, 2017
    9
    去搞清楚概念再来,好吗?
    wwqgtxx
    wwqgtxx
    Jun 26, 2017 via iPhone
    10
    除非你的单核并发是不允许抢占式的,否则一样会产生线程不安全

    举个简单的例子,程序 1 执行 i++,程序 2 也执行 i++
    当程序 1 将 i 值读取出来并运算后改为写入的时候,系统抢占式把控制权给个程序 2,程序 2 完整的执行完了 i++,随后系统将控制权交回给程序 1,此时的程序 1 并不知道自己被打断了,也不知道 i 已经被修改,还把之前计算好的值写入,最后结果就是 i 只加了 1,而不是加了 2
    momocraft
    momocraft
    Jun 26, 2017
    11
    如果你不做保证线程安全的事,就没什么东西是线程安全
    Finest
    Finest
    Jun 26, 2017
    12
    无法保证一段代码执行的原子性
    gogohigh
    gogohigh
    Jun 26, 2017
    13
    Concurrent 和 Parallel 是两个概念
    ShanghaiLinchong
    ShanghaiLinchong
    Jun 26, 2017
    14
    应该不是科班的
    blackjar
    blackjar
    Jun 26, 2017
    15
    你应该是混淆了并发跟并行 并发在只是 cpu 时序有交叉
    facetest
    facetest
    Jun 26, 2017
    16
    建议先补补基础知识
    20015jjw
    20015jjw
    Jun 26, 2017 via Android
    17
    @wwqgtxx 两个程序之间不能互相 access 内存吧 操作系统的虚拟内存不就 是为了避免这件事情发生的吗...
    yushiro
    yushiro
    Jun 26, 2017 via iPhone
    18
    @20015jjw 同一个程序的不同代码块可以啊,比如电子商城购买虚拟物品,同时扣款的例子,就是那个 i++的实际案例
    stephenyin
    stephenyin
    Jun 26, 2017
    19
    @20015jjw 考虑单进程多线程的情况!
    hjc4869
    hjc4869
    Jun 26, 2017 via Android
    20
    @20015jjw 两个进程可以共享内存啊
    wwqgtxx
    wwqgtxx
    Jun 26, 2017
    21
    @20015jjw 第一,大量存在单进程多线程的情况,第二,还存在进程间共享内存的情况
    honeycomb
    honeycomb
    Jun 26, 2017 via Android
    22
    单核不会出现 CPU 缓存不一致的情况,因为只有一个 CPU 核心。
    20015jjw
    20015jjw
    Jun 26, 2017 via Android
    23
    @wwqgtxx
    @hjc4869
    @stephenyin
    @yushiro

    程序不是 process 么 thread 当然可以共享 但是不同 process 不是都是自己一个虚拟内存么... 这个帖子里就写了啊
    https://stackoverflow.com/questions/11566780/process-vs-thread-can-two-processes-share-the-same-shared-memory-can-two-thr

    当然我只学过简单的操作系统 想想有修改器的存在大概 process 之间肯定也能互相 access 的吧 但是感觉可能是违背操作系统设计规范的...
    kaneg
    kaneg
    Jun 26, 2017 via iPhone
    24
    单核线程冲突的概率应该会小一些,但不会消失,毕竟不是原子性的操作会有可能被分配到 CPU 的两个时间片被两个线程分别抢占。
    其次,在多核 CPU 出现之前多线程的同步问题就出现了。
    wwqgtxx
    wwqgtxx
    Jun 26, 2017 via iPhone
    25
    @20015jjw 程序是 program 进程才是 process
    hjc4869
    hjc4869
    Jun 26, 2017
    26
    @20015jjw 但是同一个物理内存页可以被映射到两个不同的进程的地址空间里啊
    acess
    acess
    Jun 26, 2017
    27
    @20015jjw 有 WriteProcessMemory、CreateRemoteThread 等 API 可以用。
    powergx
    powergx
    Jun 26, 2017
    28
    你只要保证你的内存地址数据不会被篡改,100/1000 个线程 都是安全的
    situliang
    situliang
    Jun 26, 2017
    29
    是时候补习一波操作系统了
    yushiro
    yushiro
    Jun 26, 2017 via iPhone
    30
    @20015jjw 不同的 process 的确如你所说,但是 web server 是同一个 process 处理大量请求(同一个域名站点),所以会发生我说的情况
    bigdogbigpig
    bigdogbigpig
    Jun 27, 2017 via iPhone
    31
    2333,看书去
    20015jjw
    20015jjw
    Jun 27, 2017 via Android
    32
    @hjc4869 这不就违背了虚拟内存的定义么...
    msg7086
    msg7086
    Jun 27, 2017
    33
    不管操作系统怎么保护内存,也有可能两个程序读写同一个文件造成线程不安全的。
    hjc4869
    hjc4869
    Jun 27, 2017 via Android
    34
    @20015jjw 并没有,因为共享内存之后两个进程的地址空间仍然是独立的,虚拟内存的定义并没有规定物理页一定被某个地址空间独占。
    20015jjw
    20015jjw
    Jun 27, 2017 via Android
    35
    @hjc4869 对 但是系统会控制不让一段物理内存被俩程序同时使用啊 http://www.read.seas.harvard.edu/~kohler/class/05s-osp/notes/notes9.html 注意粗体
    > The different processes' memory spaces must be isolated from each other, and from the kernel.
    我 os 课的理解就是 虽然每个 process 看内存都是和系统内存一样大的 比如 0x0000-0xffff 但是俩程序不用满整个系统内存的时候 俩程序所占内存的真实地址永远不会重叠 即便在他们自己眼中可能都在 0x00ff 的地方写东西 但是这俩 00ff 由于虚拟内存的关系 在实际内存中的位置不一样
    hjc4869
    hjc4869
    Jun 27, 2017 via Android
    36
    @20015jjw 我没说地址空间自己会重叠,我指的是现代 OS 在进程主动要求的前提下 OS 会允许两个独立的进程将同一部分物理内存页映射到它们各自的地址空间内。这个叫做 shared memory,是一类非常常用的跨进程通讯手段,通常搭配其它同步、互斥方式,在对数据交换有非常高的性能要求时会使用。比如 Linux 下的 X11,在本机就是使用 MIT-SHM 扩展,利用共享内存交换数据,其原理就是将相同的物理内存页同时映射到多个进程的地址空间。

    因此上面说的跨进程 i++问题是可能存在的

    具体的 API 参考:
    Windows: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx
    Linux: http://man7.org/linux/man-pages/man7/shm_overview.7.html
    wwqgtxx
    wwqgtxx
    Jun 27, 2017
    37
    @20015jjw 只能说你看的“操作系统设计规范”可能已经过时了,在实际工作中,进程直接 share memery 是非常常见的事情,有些高级语言甚至直接在标准库中提供了接口,比如 Python 的 multiprocessing.Value, multiprocessing.Array 都可以直接直接在两个或者多个进程直接直接共享同一块内存,以减小本机程序之间 RPC 调用带来的不必要的性能损耗
    wwqgtxx
    wwqgtxx
    Jun 27, 2017
    38
    而且两个进程直接会产生线程不安全的情况并不是只有同时读写同一块内存区域这一种,如果同时读写同一个 FILE,或者同时读写同一个 MMAP 分配的空间,同时读写一个共享的 socket 都可以造成线程不安全,以及父进程和子进程同时读写同一个打开的句柄或者管道
    icegreen
    icegreen
    Jun 27, 2017
    39
    收获一枚面试题~
    20015jjw
    20015jjw
    Jun 27, 2017 via Android
    40
    @wwqgtxx 嘛 入门课 我也知道有 process 之间分享内存的 只是老师表示这个课不考虑 谢谢你提供的知识啦
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1490 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 66ms · UTC 16:38 · PVG 00:38 · LAX 08:38 · JFK 11:38
    ♥ Do have faith in what you're doing.