Google 了一下 "Python" "CAS",只是搜到了一些关于 GIL 的 ATOMIC 操作。
但是觉得 Python 的 Lock() 又有点沉,有大佬知道有没有类似 CAS 的轻量级实现吗?

统一回复了,我是使用一个标记变量 + 短代码实现类似 CAS 的效果,在 for _ in range(1000000):加法中四个线程大概用时 5 秒,并保证了总数是 4000000 。
而直接使用 Lock 耗时是 17 秒。

GIL 在 Python2 中是 1000 行字节码切换线程,Python3 中是 15 毫秒切换线程。list.pop 这种 C 调用是 atomic 的。

等一个莫名其妙喷 java 的
不过也有可能没有,因为 cas 不多学点 java 还真不知道是什么

java 被喷不是语言的问题,正是因为你这种 java boy 太多,让我等羞于为伍,说自己写过几年 java 都心惊胆战怕被人误认为你们。
cas 和 java 又有什么关系了?人家实现 cas 的时候还没现代操作系统呢,你家 jvm 都没地方跑谢谢。

#2 "等一个莫名其妙喷 java 的"你可真会咬钩
我没说 cas 跟 java 有关系,只是某些喷 java 的喜欢带上
同理设计模式也跟 java 没啥关系,还不是天天喷 java 设计模式滥用?
还羞与为伍,笑死

没发现有, python 单进程的, 直接用 Lock().

???为什么喷 Java 要带上 CAS 啊,你说设计模式我还能理解

没有而且不需要。因为 GIL 直接保证了同步。

GIL 不等于线程安全,GIL 不保证线程变量同步。

#5 设计模式不是 java 独有的,也不是 java 发明
cas 不是 java 独有的,也不是 java 发明

设计模式跟语言无关 , 基本上有点名气的开源项目里面都是设计模式的影子在里面

stackoverflow.com/questions/45802491/compare-and-swap-instruction-in-python

Python 一般我都用 Lock() 来确保类似 i += 1 这种操作的原子性, 之前查找资料有实现原子性的一些库, 不过没用过.

Python 的 CAS 将是一场灾难啊。。。GIL 把一个忙等待的线程切了进来。。。

#6 保证不了,不说 if 和赋值之间会不会切线程,就是赋值也不一定安全

CAS 是 cpu 指令级提供的冲突处理的,python 一个+1 操作都好多条 cpu 指令了,这个在 python 层面上来看已经毫无意义了吧

比较难想象 Python 怎么 CAS,l.a = b 不是原子的,这要变成三条字节码,两个 LOAD_NAME 和一个 STORE_NAME 。
如果直接用 a = b,那你压根拿不到 a 的结果,因为 Python 没有指针,函数里赋值过去就没了。
如果用 nonlocal global 去修复拿结果的问题,那就没办法做到无副作用,而且这只是换了个 name,对象所在的内存还是没有变化。

综上所述,建议直接 threading.Lock,不会有人上了 Python 还扣这个锁的性能吧?大可不必啊

在 CPython 虚拟机里,是按照字节码来逐个执行的。对于一个单进程 CPython 程序来说,字节码层面的原子性就足够了,CPU 级别的才是没有意义。

赋值都不安全?看来我孤陋寡闻了。233

#16 但这个实现没啥现实意义啊,CPU 级 CAS 的价值是在多核中,CAS 可以通过占用少量 CPU 时间来换取通过更重度的锁来导致线程休眠切换调度的问题,同时还可以最大限度保护内核缓存失效的问题,毕竟现代 cpu 和缓存速度太快了,但是你在 Python 层面做一个这东西似乎啥都没解决吧,没啥意义确实没啥提供的必要

为了 CAS 而上 CAS 的人还是挺多的,毕竟是吹嘘的资本,尽管在他们手里几乎解决不了任何实际问题。

#17 最简单一条赋值语句一般有三条 bytecode 组成,单条 bytecode 是线程安全的,多条之间不是,你可以用 dis 显示下编译出的 bytecode 就知道了

#19 确实了,Python 上 CAS 确实是为了 CAS 而 CAS 了,毕竟 GIL 限制了,不过如果你搞个扩展释放掉 GIL 的话就可以搞了

看完讨论。。我以为是 CAS 单点登录,我还纳闷这有啥好讨论的。。。落伍了落伍了

搜 atomic 好像有几个,试试看?

我还以为是 computer algebra system,差点开始安利 SageMath (

搞扩展那也是别的语言了,一般是 C,C 的 CAS 这资料还不到处都是,可以说跟 Python 一点关系都没有了。哈哈哈。

docs.python.org/3.10/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe,但是这里面说 x=y,和 x.field=y 是 atomic 的。(内置类型限定)

此贴前三楼以自己为示范展示了不加控制的人类本性

点击来之前以为是计算机代数系统

我第一眼也以为是说计算机代数系统

设计模式的影子就不叫设计模式。设计模式的全部想法都是在(拙劣、错误且反思考地)尝试提取习惯性操作并为之取个名字。
你这就好比大多数语言给 a=1 取个名字叫「赋值」,然后说『( Haskell 的) let a=1 in ... 有赋值的影子』,这说明你被词汇和词义限制住了思想。

据我所知,Python 只有.append() 是 aotmic 的,有点小坑但是有 GIL 了

恕我孤陋寡闻,python 确保线程安全的一般手段应该就是 threading.Lock,还真没见过其他方式

有毒. 楼主完全没提 java 你 1L 莫名其妙来个喷 Java?

不是,你就好好学学啥是 GIL 。threading.Lock 主要是保证 PythonVM 外的临界区的。

你可以直接说你想表达的东西

#34 你可以直接说你想表达的东西

1 楼这种真的是毒瘤,立个靶子自己打,败坏社区氛围,引战

真的吗?有了 GIL 什么都不用考虑了?

Python2 中 GIL 是运行 1000 行字节码,然后切换线程,Python3 是 15 毫秒切换线程。GIL 跟线程安全根本毫无关系,除非你能精准的控制字节码的数量。其次就是,dict.append,list.pop 这种 C 语言调用实现,是 Atomic 的。

dict 没有 append,说错了,remove

def f():
...: a=1
...: b=a

2 0 LOAD_CONST 1 (1)
2 STORE_FAST 0 (a)

3 4 LOAD_FAST 0 (a)
6 STORE_FAST 1 (b)
8 LOAD_CONST 0 (None)

#26 一个赋值语句两条字节码组成,以 Python 的内存结构来说,其实就算被拆开其实越不会有副作用,所以认为是原子操作其实也没有啥问题

#39 Python 的 GIL 就是用来保证内部数据结构线程安全的,否则直接删掉 GIL 就是了啊,所以肯定必须要求是单条字节码完整执行完成才能切换,不可能像操作系统线程一样时间一到啥都不管就直接切换吧,否则 Python 内部自身的数据结构都有可能被破坏了,从这一点上来说,GIL 保证单条字节码的完整性,确实提供了大量线程安全的操作,比如赋值,不能说毫无关系吧

嗯嗯,毫无关系确实不至于,对象内部的线程安全确实没错,不过问题是只有 CPython 存在 GIL,JPython 是没有的。

GIL 是用来保证对象内部线程安全怎么理解,什么是内部对象,那些场景线程安全?

应该是只有单字节码的操作才能保证线程安全。a=a+1 应该都不是

GIL 锁不能完全解决线程安全问题,举个例子:一个线程遍历 dict,另一个删除。线程安全问题不仅是一行语句的安全

晕...我上面不是说了吗...保证对象的 pop,append 线程安全,内部的,不是两个线程同时操作。我没说两个线程同时操作线程安全。因为 pop 和 append 是 C 语言调用,C 语言调用的都是 ATOMIC 的。

人家说的是内部数据结构,是 pop,remove 等内部的操作,不是让你两个线程同时操作的...理解错了吧兄弟

Python 解释器也需要用内存,也有数据结构啊,编译,创建类,模块导入,线程创建,文件操作,套接字这些底层也是用 GIL 保证线程安全的吧