首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  程序员

请问各位实现线程安全除了加锁还能有啥别的操作

  •  
  •   qyizhong · 145 天前 · 2128 次点击
    这是一个创建于 145 天前的主题,其中的信息可能已经有所发展或是发生改变。

    上周被问到的问题,一下把我问蒙了。问了一下周围的朋友感觉并不是我想要的答案,各位大佬们有好的解答吗

    33 回复  |  直到 2019-06-12 14:25:54 +08:00
        1
    sbw   145 天前
    无锁队列
        3
    theOneMe   145 天前
    1:cas;
    2: 变量不可变 例如 final 修饰等等;
    3: ThreadLocal
        4
    mattx   145 天前 via iPhone
    用原子变量实现 lock free
        5
    lyy16384   145 天前
    使用不可变对象
        6
    bxqqq   145 天前
    锁本来就是一种排队啊,你维护一个队列。
        7
    wr410   145 天前
    读的变量不写,写的变量不读。 (误
        8
    gz911122   145 天前
    只用一个线程来处理
        9
    kzfile   145 天前
    不使用多线程
        10
    justfly   145 天前
    本质上就是利用 atomic,对应 CPU 的 CMPXCHG。CAS,无锁队列都是在这个基础上实现的。
        11
    raysonx   145 天前 via Android
    1. 只读。
    2. 用原子变量,配合无锁( lock-free )算法。然而编程语言中原子变量的实现在某些平台可能是特定的 CPU 指令( memory barriers ),也有可能还是锁。
        12
    brust   145 天前
    mq?或者 redis 锁 zk 锁 etcd 锁
        13
    ctrlaltdeletel   145 天前
    个人的想法,不一定正确 /完整…

    - 将线程不安全的操作同步起来(加锁 /使用队列等)
    - 将导致线程不安全的资源封闭起来或去掉( ThreadLocal/只读公共的资源)
        14
    Aresxue   145 天前
    1.不要跨线程访问共享变量;
    2.使共享变量是 final 类型的;
    3.将共享变量的操作加上同步;
    3.1 java 自身
    3.1.1 锁,包括 synchronied 和 lock
    3.1.2 cas,例如 ConcurrentHashMap
    3.1.3 复制变量,一种用空间换时间的方式,典型的如 ThreadLocal ;
    3.1.4 原子变量,LongAdder 和 Atomic*;
    3.2 中间件,这个太多,缓存比如 redis、zookeeper、数据库()甚至文件都可以做。
    ps:java 自身适用于单机情况,分布式下中间件一般更优。
        15
    russian   145 天前
    放弃线程使用异步。。。我觉得 cpu 怎么都不可能成为短板把。绝大多数情况还是 io
        16
    mooncakejs   145 天前
    CAS, COW
        17
    corvofeng   145 天前 via Android
    突然想到, 你可以用协程, 这样就不用考虑线程安全了, 考虑进程安全就行了🤣
        18
    lihongjie0209   145 天前   ♥ 1
    线程安全的本质就是 共享 + 可变
    1. 从不共享的角度来看,

    1.1 单线程无共享, redis
    1.2 多线程, threadLocal, 每个线程都操作自己的数据

    2. 从不可变的角度来看

    2.1 使用不可变的数据结构和对象

    如果使用上述的方法还是解决不了你的问题,那么你就需要一些第三方的服务, 如锁,分布式锁等来保证在某一个具体的时刻, 你的资源只能处于一个状态: 要么共享, 要么可变
        19
    Moker   145 天前
    @corvofeng 不同协程一起读一个变量 还是 GG
        20
    ryd994   145 天前 via Android
    @bxqqq 锁可以不保证 FIFO


    @wr410 实际上还是需要原子性。举个例子,如果你的 CPU 写某个 2 字节变量需要 2 个周期,在这两个周期内还是有可能读到错误值的
    从 0x0000 先变成 0x00FF,再变成 0xFFFF,那运气不好就会读到中间值
    这个问题很少遇到是因为一般 64 位 CPU 写 64 位或 32 位整数都是硬件原子的,所以一般没事
        21
    ryd994   145 天前 via Android
    @Moker 不会,线程内部可以保证一致性
    协程不能随便交叉读是因为 Python 或 go 作为高级语言,解释权不保证翻译的原子性。表面上是一行代码,实际上可能被翻译成多个 CPU 指令,中间可能被运行环境打断,穿插其他协程的操作。
    如果你自己手动实现异步操作,那还是可以保证安全的。因为此时就是单线程程序而已。如果连单线程都不能保证安全的话这 CPU 也就废了。
        22
    exonuclease   145 天前 via iPhone
    cas 原子变量 或者干脆不可变数据
        23
    luozic   145 天前 via iPhone
    cas cow copy on write。最经典的 java 里面的 juc Doug lea 大佬的代码
        24
    zpxshl   145 天前 via Android
    rust。。。
        25
    billlee   145 天前
    使用 immutable 数据结构, 函数式编程
        26
    jimages   145 天前
    戚总好!
    实现线程安全的办法有:
    1.一种办法是把函数写成无状态的函数,有点类似于函数式编程,这个函数中不使用任何全局变量和静态变量,只使用静态变量。
    2.加锁
    3.使用原子对象
    3.
        27
    slanternsw   145 天前 via Android
    rust(狗头保命)
        28
    beidounanxizi   145 天前
    看看 go 并发模型 总体来说就两种 共享内存 和 CSP?
        29
    lusi1990   145 天前 via Android
    只读 是线程安全的,只有一个写是线程安全的,多个写才需要考虑线程安全
        30
    yellbo1   145 天前
    线程封闭是不是也是线程安全的。。。
        31
    qyizhong   145 天前
    谢谢各位,突然知道了好多东西...
        32
    iwtbauh   145 天前 via Android
    免锁?除去线程本地变量,就只有免锁算法了,比如

    RCU 读取-拷贝-更新
    免锁队列算法

    等等
        33
    anyele   130 天前
    1,CAS
    2,队列
    3,单线程(类似于 redis)
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3228 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 26ms · UTC 04:46 · PVG 12:46 · LAX 21:46 · JFK 00:46
    ♥ Do have faith in what you're doing.