Reputation: 35
Python 3.x
import threading
lock = threading.Lock()
counter = 0
def update_counter():
global counter
lock.acquire()
counter += 1
lock.release()
# starts threads, target update_counter
Does lock have to be global as well? If not, how does it not cause an error as local lock isn't defined?
Thank you
Upvotes: 3
Views: 1689
Reputation: 1872
To answer the question directly, the reason that counter
needs to be declared global
and lock
doesn't is because you are reassigning to counter
(with counter += 1
) whereas you are only calling methods on lock
. For references to a variable, if no local variable exists Python will look in enclosing scopes until it finds a match. In this case, it finds it in the global scope. For assignments to variables, Python will assume the variable is local unless explicitly declared otherwise (with global
or nonlocal
).
Upvotes: 2
Reputation: 77367
Locks protect some resource and are generally scoped the same as the resource. In your case you are protecting a global counter so the lock must be global also. All threads that access the resource must use the same lock so it wouldn't do any good to create a private lock in the function itself - no other thread would see it.
Some applications use a single lock to protect all shared resources (course-grained locking). But you could also keep locks with the data (fine-grained locking). An example of fine grained locking is:
class MyCounter:
def __init__(self):
self.lock = threading.Lock()
self.value = 0
def increment(self):
with self.lock:
self.value += 1
Now, each instance of MyCounter
has a lock and runs independently.
Upvotes: 1