Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thread implementation #5

Closed
Fede112 opened this issue Nov 22, 2020 · 2 comments
Closed

Thread implementation #5

Fede112 opened this issue Nov 22, 2020 · 2 comments

Comments

@Fede112
Copy link

Fede112 commented Nov 22, 2020

Hi, first of all thanks for the series, it is great and really clear.
One question regarding how threads work.
When, for example, a Detector instance calls the update(self, screenshot) method:

class Detection:
    def __init__(self, model_file_path):
        # create a thread lock object
        self.lock = Lock()
    (......)
    def update(self, screenshot):
           self.lock.acquire()
           self.screenshot = screenshot
           self.lock.release()

Shouldn' t the lock acquired by the method be the one of the WindowCapture instance? I don't understand how threads are talking to each other if the locks they acquired are the ones enclosed in the objects each of them are supposed to manage.

Thanks in advance!

@learncodebygaming
Copy link
Owner

Hi, good question. When dealing with multiple threads, the disaster situation we want to avoid is having two threads edit the state of the same object at the same time. That can lead to bizarre, hard to diagnose problems.

Using the example code you pasted, if two threads each had access to the same detector object and they both called detector.update() at the same time, using the lock acquire/release would force one call to wait for the completion of the other. The first one to call update() would "block" the second thread, and the second thread would wait to run its update() call until the lock in the first thread is released. In that way we prevent the detector object from ever existing in two different states.

So the problem we're trying to solve with these locks is all on the write end. On the read side, in my experience Python doesn't care if one thread is reading a property while another thread is updating it. If both a read and write happen simultaneously, I imagine Python sends the old but complete value to the reader, but I honestly don't know the specifics on that. In our bot application, it doesn't really matter if our detector gets a slightly old screenshot from WindowCapture. That is, if the main thread calls detector.update(wincap.screenshot) while the WindowCapture thread is in the middle of updating it's screenshot with self.screenshot = screenshot, my mental picture is that detector.update() gets the prior screenshot image.

Sharing locks between threads might be needed in some situations, but then you're losing a lot of the advantage of running separate threads because you're bringing them back into synchronization. You could have the Detection object wait for the WindowCapture to finish taking the next screenshot by calling acquire() on the WindowCapture lock, but I think you'd just be slowing down the detection without much benefit. Also, keeping track of all these threads and locks gets complicated pretty quickly, and just focusing on the writes keeps things simpler.

If you are in a situation where you need to lock both the writes and the reads, here's a good example of how to do that: https://www.oreilly.com/library/view/python-cookbook/0596001673/ch06s04.html

@Fede112
Copy link
Author

Fede112 commented Nov 23, 2020

I see! If I had to guess since the screenshot is medium size array it cannot be updated all at once by a thread, so reading a partially updated screenshot can happen. Still, it has no impact if you are building a bot like this one.
As you pointed out, it is much better risking analysing some old/corrupted screenshots than paying the price of thread synchronization.
Thanks once again for the clear and complete response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants