Skip to content

Does CPython >= 3.10, <=3.12 support a thread-safe increment? #134212

@tvvister

Description

@tvvister

Documentation

There is no information about it in docs. But the code demonstrates that increment works correctly in multithreading context.

import concurrent.futures


def inc():
    global count
    for _ in range(1000):
        count += 1

for threads_count in range(1, 101):
    for _ in range(3):
        count = 0
        with concurrent.futures.ThreadPoolExecutor(max_workers=threads_count) as exe:
            for _ in range(10000):
                exe.submit(inc)

        print(f"{threads_count=}, {count=}")


import dis
dis.dis(inc)
output

threads=1, count=10000000
threads=1, count=10000000
threads=1, count=10000000
threads=2, count=10000000
threads=2, count=10000000
threads=2, count=10000000
threads=3, count=10000000
threads=3, count=10000000
threads=3, count=10000000
threads=4, count=10000000
threads=4, count=10000000
threads=4, count=10000000
threads=5, count=10000000
threads=5, count=10000000
threads=5, count=10000000
threads=6, count=10000000
threads=6, count=10000000
threads=6, count=10000000
threads=7, count=10000000
threads=7, count=10000000
threads=7, count=10000000
threads=8, count=10000000
threads=8, count=10000000
threads=8, count=10000000
threads=9, count=10000000
threads=9, count=10000000
threads=9, count=10000000
threads=10, count=10000000
threads=10, count=10000000
threads=10, count=10000000
threads=11, count=10000000
threads=11, count=10000000
threads=11, count=10000000
threads=12, count=10000000
threads=12, count=10000000
threads=12, count=10000000
threads=13, count=10000000
threads=13, count=10000000
threads=13, count=10000000
threads=14, count=10000000
threads=14, count=10000000
threads=14, count=10000000
threads=15, count=10000000
threads=15, count=10000000
threads=15, count=10000000
threads=16, count=10000000
threads=16, count=10000000
threads=16, count=10000000
threads=17, count=10000000
threads=17, count=10000000
threads=17, count=10000000
threads=18, count=10000000
threads=18, count=10000000
threads=18, count=10000000
threads=19, count=10000000
threads=19, count=10000000
threads=19, count=10000000
threads=20, count=10000000
threads=20, count=10000000
threads=20, count=10000000
threads=21, count=10000000
threads=21, count=10000000
threads=21, count=10000000
threads=22, count=10000000
threads=22, count=10000000
threads=22, count=10000000
threads=23, count=10000000
threads=23, count=10000000
threads=23, count=10000000
threads=24, count=10000000
threads=24, count=10000000
threads=24, count=10000000
threads=25, count=10000000
threads=25, count=10000000
threads=25, count=10000000
threads=26, count=10000000
threads=26, count=10000000
threads=26, count=10000000
threads=27, count=10000000
threads=27, count=10000000
threads=27, count=10000000
threads=28, count=10000000
threads=28, count=10000000
threads=28, count=10000000
threads=29, count=10000000
threads=29, count=10000000
threads=29, count=10000000
threads=30, count=10000000
threads=30, count=10000000
threads=30, count=10000000
threads=31, count=10000000
threads=31, count=10000000
threads=31, count=10000000
threads=32, count=10000000
threads=32, count=10000000
threads=32, count=10000000
threads=33, count=10000000
threads=33, count=10000000
threads=33, count=10000000
threads=34, count=10000000
threads=34, count=10000000
threads=34, count=10000000
threads=35, count=10000000
threads=35, count=10000000
threads=35, count=10000000
threads=36, count=10000000
threads=36, count=10000000
threads=36, count=10000000
threads=37, count=10000000
threads=37, count=10000000
threads=37, count=10000000
threads=38, count=10000000
threads=38, count=10000000
threads=38, count=10000000
threads=39, count=10000000
threads=39, count=10000000
threads=39, count=10000000
threads=40, count=10000000
threads=40, count=10000000
threads=40, count=10000000
threads=41, count=10000000
threads=41, count=10000000
threads=41, count=10000000
threads=42, count=10000000
threads=42, count=10000000
threads=42, count=10000000
threads=43, count=10000000
threads=43, count=10000000
threads=43, count=10000000
threads=44, count=10000000
threads=44, count=10000000
threads=44, count=10000000
threads=45, count=10000000
threads=45, count=10000000
threads=45, count=10000000
threads=46, count=10000000
threads=46, count=10000000
threads=46, count=10000000
threads=47, count=10000000
threads=47, count=10000000
threads=47, count=10000000
threads=48, count=10000000
threads=48, count=10000000
threads=48, count=10000000
threads=49, count=10000000
threads=49, count=10000000
threads=49, count=10000000
threads=50, count=10000000
threads=50, count=10000000
threads=50, count=10000000
threads=51, count=10000000
threads=51, count=10000000
threads=51, count=10000000
threads=52, count=10000000
threads=52, count=10000000
threads=52, count=10000000
threads=53, count=10000000
threads=53, count=10000000
threads=53, count=10000000
threads=54, count=10000000
threads=54, count=10000000
threads=54, count=10000000
threads=55, count=10000000
threads=55, count=10000000
threads=55, count=10000000
threads=56, count=10000000
threads=56, count=10000000
threads=56, count=10000000
threads=57, count=10000000
threads=57, count=10000000
threads=57, count=10000000
threads=58, count=10000000
threads=58, count=10000000
threads=58, count=10000000
threads=59, count=10000000
threads=59, count=10000000
threads=59, count=10000000
threads=60, count=10000000
threads=60, count=10000000
threads=60, count=10000000
threads=61, count=10000000
threads=61, count=10000000
threads=61, count=10000000
threads=62, count=10000000
threads=62, count=10000000
threads=62, count=10000000
threads=63, count=10000000
threads=63, count=10000000
threads=63, count=10000000
threads=64, count=10000000
threads=64, count=10000000
threads=64, count=10000000
threads=65, count=10000000
threads=65, count=10000000
threads=65, count=10000000
threads=66, count=10000000
threads=66, count=10000000
threads=66, count=10000000
threads=67, count=10000000
threads=67, count=10000000
threads=67, count=10000000
threads=68, count=10000000
threads=68, count=10000000
threads=68, count=10000000
threads=69, count=10000000
threads=69, count=10000000
threads=69, count=10000000
threads=70, count=10000000
threads=70, count=10000000
threads=70, count=10000000
threads=71, count=10000000
threads=71, count=10000000
threads=71, count=10000000
threads=72, count=10000000
threads=72, count=10000000
threads=72, count=10000000
threads=73, count=10000000
threads=73, count=10000000
threads=73, count=10000000
threads=74, count=10000000
threads=74, count=10000000
threads=74, count=10000000
threads=75, count=10000000
threads=75, count=10000000
threads=75, count=10000000
threads=76, count=10000000
threads=76, count=10000000
threads=76, count=10000000
threads=77, count=10000000
threads=77, count=10000000
threads=77, count=10000000
threads=78, count=10000000
threads=78, count=10000000
threads=78, count=10000000
threads=79, count=10000000
threads=79, count=10000000
threads=79, count=10000000
threads=80, count=10000000
threads=80, count=10000000
threads=80, count=10000000
threads=81, count=10000000
threads=81, count=10000000
threads=81, count=10000000
threads=82, count=10000000
threads=82, count=10000000
threads=82, count=10000000
threads=83, count=10000000
threads=83, count=10000000
threads=83, count=10000000
threads=84, count=10000000
threads=84, count=10000000
threads=84, count=10000000
threads=85, count=10000000
threads=85, count=10000000
threads=85, count=10000000
threads=86, count=10000000
threads=86, count=10000000
threads=86, count=10000000
threads=87, count=10000000
threads=87, count=10000000
threads=87, count=10000000
threads=88, count=10000000
threads=88, count=10000000
threads=88, count=10000000
threads=89, count=10000000
threads=89, count=10000000
threads=89, count=10000000
threads=90, count=10000000
threads=90, count=10000000
threads=90, count=10000000
threads=91, count=10000000
threads=91, count=10000000
threads=91, count=10000000
threads=92, count=10000000
threads=92, count=10000000
threads=92, count=10000000
threads=93, count=10000000
threads=93, count=10000000
threads=93, count=10000000
threads=94, count=10000000
threads=94, count=10000000
threads=94, count=10000000
threads=95, count=10000000
threads=95, count=10000000
threads=95, count=10000000
threads=96, count=10000000
threads=96, count=10000000
threads=96, count=10000000
threads=97, count=10000000
threads=97, count=10000000
threads=97, count=10000000
threads=98, count=10000000
threads=98, count=10000000
threads=98, count=10000000
threads=99, count=10000000
threads=99, count=10000000
threads=99, count=10000000
threads=100, count=10000000
threads=100, count=10000000
threads=100, count=10000000
11 0 LOAD_GLOBAL 0 (range)
2 LOAD_CONST 1 (1000)
4 CALL_FUNCTION 1
6 GET_ITER
>> 8 FOR_ITER 6 (to 22)
10 STORE_FAST 0 (_)

12 12 LOAD_GLOBAL 1 (count)
14 LOAD_CONST 2 (1)
16 INPLACE_ADD
18 STORE_GLOBAL 1 (count)
20 JUMP_ABSOLUTE 4 (to 8)

11 >> 22 LOAD_CONST 0 (None)
24 RETURN_VALUE

Looks like '+=' isn't an atomic op. But stiil I have a correct result.

Can we just use it as a guarantee or it is just an accent coincidence?

Metadata

Metadata

Assignees

No one assigned

    Labels

    docsDocumentation in the Doc dir

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions