Threading Oddity?

K

Kris Caselden

I noticed a strange yet easily fixed problem in Python's thread
module.

Consider the following code:

#-------------------------------

import thread

data='this is data'
data_mutex = thread.allocate_lock()

def thread1():
while data_mutex.locked():
data_mutex.aquire()
print 'thread1:',data
if data_mutex.locked():
data_mutex.release()

def thread2():
while data_mutex.locked():
data_mutex.aquire()
print 'thread2:',data
if data_mutex.locked():
data_mutex.release()

thread.start_new_thread(thread1,())
thread.start_new_thread(thread2,())

#-------------------------------

This code runs as expected. However, take away the while loop checks
for mutex lock and Python is unable to properly acquire the lock,
complaining of an unhandled exception. The Python Library Reference
mentions that "this method acquires the lock unconditionally, if
necessary waiting until it is released by another thread (only one
thread at a time can acquire a lock -- that's their reason for
existence), and returns None." You'd think one wouldn't have to check
if the lock is locked, especially when acquire is supposed to wait for
the lock to be freed. At first, I thought this problem had to do with
aquire()'s waitflag, but the problem exists regardless of waitflag's
value.

Does anyone know why this problem exists, and if my code works around
it? It would seem that locked() and acquire() would not necessarily be
run uninterrupted, and so mutual exclusion could not be guaranteed.
 
K

Kevin

use this instead and you're fine:

import threading
data_mutex = threading.Lock()

using the thread module directly is depreciated, and the threading.Lock()
object works as you expect without having to check if it's locked before
acquiring it.

Kevin
 
C

Christos TZOTZIOY Georgiou

On 22 Aug 2003 21:33:18 -0700, rumours say that
(e-mail address removed) (Kris Caselden) might have written:

[code snip]
def thread1():
while data_mutex.locked():
data_mutex.aquire()
print 'thread1:',data
if data_mutex.locked():
data_mutex.release()
[code snip]

Kris, please copy-paste *real* code. This is not code you ran, this was
written for the sake of the post. thread.lock object has no attribute
"aquire".
This code runs as expected. However, take away the while loop checks
for mutex lock and Python is unable to properly acquire the lock,
complaining of an unhandled exception.

I never had any problems with thread.lock.acquire, and I use it a lot.
Please come back with the code that fails for you, and specify the
environment (OS, python version, whether you built it from sources, if
you applied any changes to the source etc).

The following program runs fine for me on Linux, Irix and Windows 2k:

import thread, time

data='this is data'
data_mutex = thread.allocate_lock()

def thread1():
data_mutex.acquire()
print 'thread1:',data
data_mutex.release()

def thread2():
data_mutex.acquire()
print 'thread2:',data
data_mutex.release()

thread.start_new_thread(thread1,())
thread.start_new_thread(thread2,())
time.sleep(1)

I inserted the time.sleep(1) to allow for the threads to run before the
program ends (and thus the threads end prematurely). threading would
allow you to .join the threads instead.
 
K

Kris Caselden

Christos "TZOTZIOY" Georgiou said:
Kris, please copy-paste *real* code. This is not code you ran, this was
written for the sake of the post. thread.lock object has no attribute
"aquire".

You lost me for a second, until I realized that "aquire" and "acquire"
are two different words ;) Sigh. However, my code does indeed run,
without error, which begs the question; how is this working?

Anyways, thanks for the fix.
 
C

Christos TZOTZIOY Georgiou

However, my code does indeed run,
without error, which begs the question; how is this working?

Kris, I believe your code runs without error in your hardware, and I
also know my code runs without error on my hardware. What your post
initially implied is that /my/ code wouldn't run on /your/ hardware
unless you wrapped the acquire calls in "while loop checks for mutex
lock". Did you run my code successfully? If yes, we can skip that
question as implicitly answered, if not, come back with more info.

In your latest question, "how is this working?", do you mean how mutex
locks work? The answer to this is that there are operating system calls
whose purpose is to implement such locks, and Python builds on that. If
I did not understand your question, please let me know.
 
J

Jeff Epler

I noticed a strange yet easily fixed problem in Python's thread
module.

Consider the following code:

#-------------------------------

import thread

data='this is data'
data_mutex = thread.allocate_lock()

def thread1():
while data_mutex.locked():
data_mutex.aquire()
print 'thread1:',data
if data_mutex.locked():
data_mutex.release()

def thread2():
while data_mutex.locked():
data_mutex.aquire()
print 'thread2:',data
if data_mutex.locked():
data_mutex.release()

thread.start_new_thread(thread1,())
thread.start_new_thread(thread2,())

This code didn't run for me (no lines were printed) because the program
exits when the main thread is done. I added
import time
time.sleep(1)
after the start_new_thread calls as a remedy. Then, it printed two
lines and waited about a second before I got the prompt back.

I tried removing the 'while's and dedenting the lines
"data_mutex.aquire". Then I got an attribute error!

But with the "while", there's no error. Why not? Because the mutex was
never locked! If the mutex is not locked, the body of the while statement
is not executed. On the other hand, if the statement inside the loop
was executed and did successfully claim the mutex, the 'while' condition
would evaluate to 'true' the next time through, the statement to claim
the lock would execute again, and block forever. (but this isn't likely
to happen on any particular run, because it would require that the mutex
be released at just the right moment.. properly testing threaded code is
hard)

I think this comes down to being a typo (as pointed out by another
poster, acquire vs aquire) and the addition of the 'while' loop just
adds confusion and is a completely wrong thing to do.

Jeff
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,121
Latest member
LowellMcGu
Top