0

I already read this topic, but when I try to run this code, I will a little delta

import threading
from threading import Thread
from cryptography.fernet import Fernet
import time
from multiprocessing import Process



def create_key1():

    print(time.time())


def create_key2(): 

    print(time.time())  

if __name__ == '__main__':
    Process(target = create_key1()).start()
    Process(target = create_key2()).start()

    Thread(target = create_key1()).start()
    Thread(target = create_key2()).start()

if we comment Process and run the code, we will see the result :

1501843580.508508
1501843580.5089302

if we comment Thread and run the code, we will see the result :

1501843680.4178944
1501843680.420028

we got delta at the same situation, my question is how to run threads at the same time, be cause I want check generation of the key in cryptography python library. I want to check what will if I try to generate two keys at same time, will they same or not.

Kallz
  • 3,244
  • 1
  • 20
  • 38
Anton
  • 209
  • 2
  • 6
  • 15
  • I'm not certain as to what you want, but I'll give my best guess as to what you are asking: You are asking if when two threads run, either with the `multiprocessing` or `threading` modules, will they run at the exact same time. You are asking if you base a cryptographic key off the current time, will they give the same result from both methods. Are my assumptions about what you are asking correct? – Jake Conkerton-Darby Aug 04 '17 at 11:01
  • yes, you are made correct assumptions – Anton Aug 04 '17 at 11:04
  • To be clear, you never did a single thing in a thread or process here, because you called your functions and passed their return values as the `target`. You wanted `target=create_key1`, not `target=create_key1()` (same for the other `target` usages). – ShadowRanger Nov 16 '22 at 18:01

2 Answers2

0

Parallel processing of two functions, as in your code, does not guarantee that the functions will run at exactly the same time. As you have seen there is a slight discrepancy in the time that the methods reach the time.time() call, and this is to be expected.

In particular due to the way that the threading module is designed it isn't possible for the methods to run at exactly the same time. Similarly, while the multiprocessing module could theoretically run two functions at the exact same time there is no guarantee of this, and it is likely to be a rare occurrence.

In the end this is butting up against the low level constraints of an operating system, where two pieces of code can't physically be run at the same time on the same processing core.

To answer your question on how this will affect the keys produced by your code, it depends on how sensitive your algorithm to the current time. If your algorithm bases a key of the current time to the nearest second, or tenth of a second then the keys produced will likely be identical (but are not guaranteed to be). However if the keys produced are based on the exact time that the function call is reached then they are unlikely to ever match, as there is no guarantee of the time the function calls will be reached in the two functions.

For more information on the differences between the threading and multiprocessing modules see this.

Edit: ShadowRanger made a good comment about some context I missed when I originally answered this question, I've copied the comment below for best clarity:

This answer is correct in the general, but wrong in the specifics. The OP wasn't even running their code in processes or threads; they ran it in the main thread in the main process, then launched no-op threads/processes (because it used the return value of the functions as the target, and it was None). To make it actually do anything outside the main thread, you'd need to use target=create_key1 (which passes the uncalled function in to be run in the thread/process), not target=create_key1() (which runs the function and passes its return value in as the target).

  • This answer is correct in the general, but wrong in the specifics. The OP wasn't even running their code in processes *or* threads; they ran it in the main thread in the main process, then launched no-op threads/processes (because it used the return value of the functions as the target, and it was `None`). To make it actually do *anything* outside the main thread, you'd need to use `target=create_key1` (which passes the uncalled function in to be run in the thread/process), not `target=create_key1()` (which runs the function and passes its return value in as the target). – ShadowRanger Nov 16 '22 at 18:00
  • Huh, you're entirely correct, thank you for taking the time to note this, I'll edit the answer to highlight your comment so people can see the right context. – Jake Conkerton-Darby Apr 28 '23 at 11:03
0

The GIL is an interpreter-level lock. This lock prevents the execution of multiple threads at once in the Python interpreter. Each thread that wants to run must wait for the GIL to be released by the other thread, which means your multi-threaded Python application is essentially single threaded,

Another approach is to use the multiprocessing module where each process runs in its own OS process with its own Python runtime. You can take full advantage of multiple cores with this approach, and it's usually safer because you don't have to worry about synchronising access to shared memory.

for more info about [GIL]1

Kallz
  • 3,244
  • 1
  • 20
  • 38