0

When we run one thread application it's looks easy. CPython interpreter run one by one bytecode instruction and execute it immediately. But if we start another thread from the first one does it have its own loop consuming bytecode and they share some common memory for synchronization(GIL, etc) or somehow loop from first(main) thread delegate instructions for second? Thing I can't figure out how second thread gets instructions what it need to execute if need to be constantly interpreted. I understand that it won't run in parallel because of GIL, but question about interpreting instructions, does it happens in both threads?

import threading

def thread_function(value):
    print(value)

if __name__ == "__main__":

    x = threading.Thread(target=thread_function, args=(1,))
    x.start()

in which thread print(value) will be interpreted(main or child)?

Sergii V.
  • 191
  • 1
  • 13
  • Sometimes you just don't need to know these details. – quamrana Nov 07 '19 at 15:12
  • The time is come up!) – Sergii V. Nov 07 '19 at 15:36
  • Does this answer your question? [How do threads work in Python, and what are common Python-threading specific pitfalls?](https://stackoverflow.com/questions/31340/how-do-threads-work-in-python-and-what-are-common-python-threading-specific-pit) – quamrana Nov 07 '19 at 15:39
  • No, it's all about GIL. I understand that it won't run in parallel, but it uses native threads and it require instructions to execute – Sergii V. Nov 07 '19 at 15:46
  • 1
    Python itself simply doesn't specify how this works; it's an implementation detail. The GIL *itself* is an implementation detail of CPython, not something the language specifies. – chepner Nov 07 '19 at 15:55
  • thanks, update question to be CPython specific – Sergii V. Nov 07 '19 at 16:00
  • It's one of the most discussed issues and it seems very difficult to change. For the time being. Python threading is kind of useless (performance wise) if you do not have code, that blocks due to IO, that has sleeps or that uses modules with native code (e.g. numpy) , that do release the GIL. For all other cases use multiprocessing instead of multithreading – gelonida Nov 07 '19 at 16:05
  • normally you should not have to know anything else about threads than what I mentioned above. If you believe you do, then I suggest you post the code snippet, that requires such a knowledge and we can advise on the given example or how to code it such, that no knowledge about implementation details is required. Coding too close to nitty gritty implementation details is most of the times not a good idea. – gelonida Nov 07 '19 at 16:07
  • Question not about GIL! I just trying to figure out how interpreter work – Sergii V. Nov 07 '19 at 16:07
  • all data exchange between threads must be properly exchanged with thread safe mechanisms as in any other programming language. You have mutexes (Locks) queues and events to perform safe inter thread communication – gelonida Nov 07 '19 at 16:10
  • You get the most useful answers at SO if you post a small example with a given problem and ask how to fix it or if you post a small example and ask if it is thread safe or a small example, that does almost what you want, and ask for help for a specific point – gelonida Nov 07 '19 at 16:12
  • update question – Sergii V. Nov 07 '19 at 16:18

1 Answers1

1

I think reading CPython code will be helpful.

You will find all details required in ceval.c

I am pretty new to CPython as well. I will try to share my understanding.

  1. main loop (run forever or python interpretation loop start at line 1184, for(;;)
  2. you could try dis module and understand how python code is converted into bytecode
  3. interpreter will take byte code and execute one by one
  4. how thread switches? line 1233-1250, threads switch

You could imagine that once you call threading.Thread, bytecode for creation of thread object and its target function will be added to current instruction list.

When interpreter handle this bytecode, it will notice that a new thread is created(this step I am not really sure. You could check ceval.py and threading module to verify).

Now you have two list of bytecode for python interpreter to consume.

It will take turns according to its own rules (i.e. per thread per 100 instructions then decide whether to switch, special signal handling or others)

Hope it answers your doubts.

Seeking deep understanding and not taking anything for granted is great!

Hope you could have good time exploring cpython.

White
  • 627
  • 4
  • 10
  • I really appreciate your attention. That exactly what I was doing. After further investigation I found pseudo code snippet(https://rushter.com/blog/python-gil-thread-scheduling/) showing that loop execution in each thread. And it resolves question, how interpreted bytecode(machine code) can gets in child thread, and it can't. There is no Interpreting control thread. Interpreter is same c code in different threads, which share some structures. – Sergii V. Nov 11 '19 at 13:17