Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > locks

Reply
Thread Tools

locks

 
 
Ajay
Guest
Posts: n/a
 
      10-13-2004
hi!

what would happen if i try to access a variable locked by another thread? i
am not trying to obtain a lock on it, just trying to access it.

cheers





----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.
 
Reply With Quote
 
 
 
 
Diez B. Roggisch
Guest
Posts: n/a
 
      10-13-2004
Ajay wrote:

> what would happen if i try to access a variable locked by another thread?
> i am not trying to obtain a lock on it, just trying to access it.


If you first tell us haw you actually lock a variable, we then might be able
to tell you what happens if you access it....

And in general: python has the PIL - Python Interpreter Lock - that
"brutally" serializes (hopefully) all accesses to python data-structures -
so e.g. running several threads, appending to the same list, won't result
in messing up the internal list structure causing segfaults or the like.
That makes programming pretty easy, at the cost of lots of waiting for the
individual threads.

--
Regards,

Diez B. Roggisch
 
Reply With Quote
 
 
 
 
Cliff Wells
Guest
Posts: n/a
 
      10-13-2004
On Wed, 2004-10-13 at 14:11 +0200, Diez B. Roggisch wrote:
> Ajay wrote:
>
> > what would happen if i try to access a variable locked by another thread?
> > i am not trying to obtain a lock on it, just trying to access it.

>
> If you first tell us haw you actually lock a variable, we then might be able
> to tell you what happens if you access it....
>
> And in general: python has the PIL - Python Interpreter Lock - that


I think you mean the GIL (Global Interpreter Lock). PIL is the
excellent Python Imaging Library.

> "brutally" serializes (hopefully) all accesses to python data-structures -


Nope. It doesn't do this. For access to items such as integers you are
probably fine, but for things like lists, dictionaries, class
attributes, etc, you're on your own. The GIL only ensures that two
threads won't be executing Python bytecode simultaneously. It locks the
Python *interpreter*, not your program or data structures.

> so e.g. running several threads, appending to the same list, won't result
> in messing up the internal list structure causing segfaults or the like.


True, you won't get segfaults. However, you may very well get a
traceback or mangled data.

> That makes programming pretty easy, at the cost of lots of waiting for the
> individual threads.


Threading in Python is pretty easy, but certainly not *that* easy. And
just to be certain, importing PIL won't help you here either <wink>.

Regards,
Cliff

--
Cliff Wells <(E-Mail Removed)>

 
Reply With Quote
 
Fredrik Lundh
Guest
Posts: n/a
 
      10-13-2004
Diez B. Roggisch wrote:

> And in general: python has the PIL - Python Interpreter Lock -


the lock is usually known as GIL (Global Interpreter Lock). see:

http://docs.python.org/api/threads.html

PIL is something else:

http://www.google.com/search?q=PIL

</F>



 
Reply With Quote
 
Diez B. Roggisch
Guest
Posts: n/a
 
      10-13-2004
> I think you mean the GIL (Global Interpreter Lock). PIL is the
> excellent Python Imaging Library.


I certainly did - to less caffeine in system yet...


> Nope. It doesn't do this. For access to items such as integers you are
> probably fine, but for things like lists, dictionaries, class
> attributes, etc, you're on your own. The GIL only ensures that two
> threads won't be executing Python bytecode simultaneously. It locks the
> Python *interpreter*, not your program or data structures.

<snip>
> True, you won't get segfaults. However, you may very well get a
> traceback or mangled data.


I thougth that e.g. list manipulations are bytecodes, thus atomic.
So far, I never ran into serious problems giving me garbage lists or
stacktraces.

Nevertheless, I of course used queues and locked access to certain
datastructures when critical sections had to be entered - but in
comparision to java, I never had to ask for a specially thread-hardened
variant of a collection.


> Threading in Python is pretty easy, but certainly not *that* easy. And
> just to be certain, importing PIL won't help you here either <wink>.


Unless you plan to do some nifty image manipulation work multithreaded....
--
Regards,

Diez B. Roggisch
 
Reply With Quote
 
Peter L Hansen
Guest
Posts: n/a
 
      10-13-2004
Cliff Wells wrote:
> On Wed, 2004-10-13 at 14:11 +0200, Diez B. Roggisch wrote:
>>"brutally" serializes (hopefully) all accesses to python data-structures -

>
> Nope. It doesn't do this. For access to items such as integers you are
> probably fine, but for things like lists, dictionaries, class
> attributes, etc, you're on your own. The GIL only ensures that two
> threads won't be executing Python bytecode simultaneously. It locks the
> Python *interpreter*, not your program or data structures.
>
>>so e.g. running several threads, appending to the same list, won't result
>>in messing up the internal list structure causing segfaults or the like.

>
> True, you won't get segfaults. However, you may very well get a
> traceback or mangled data.
>
>>That makes programming pretty easy, at the cost of lots of waiting for the
>>individual threads.

>
> Threading in Python is pretty easy, but certainly not *that* easy.


Cliff, do you have any references, or even personal experience to
relate about anything on which you comment above?

In my experience, and to my knowledge, Python threading *is*
that easy (ignoring higher level issues such as race conditions
and deadlocks and such), and the GIL *does* do exactly what Diez
suggests, and you will *not* get tracebacks nor (again, ignoring
higher level issues) mangled data.

You've tentatively upset my entire picture of the CPython (note,
CPython only) interpreter's structure and concept. Please tell
me you were going a little overboard to protect a possible
newbie from himself or something.

-Peter
 
Reply With Quote
 
Cliff Wells
Guest
Posts: n/a
 
      10-13-2004
On Wed, 2004-10-13 at 08:52 -0400, Peter L Hansen wrote:
> Cliff Wells wrote:
> > On Wed, 2004-10-13 at 14:11 +0200, Diez B. Roggisch wrote:
> >>"brutally" serializes (hopefully) all accesses to python data-structures -

> >
> > Nope. It doesn't do this. For access to items such as integers you are
> > probably fine, but for things like lists, dictionaries, class
> > attributes, etc, you're on your own. The GIL only ensures that two
> > threads won't be executing Python bytecode simultaneously. It locks the
> > Python *interpreter*, not your program or data structures.
> >
> >>so e.g. running several threads, appending to the same list, won't result
> >>in messing up the internal list structure causing segfaults or the like.

> >
> > True, you won't get segfaults. However, you may very well get a
> > traceback or mangled data.
> >
> >>That makes programming pretty easy, at the cost of lots of waiting for the
> >>individual threads.

> >
> > Threading in Python is pretty easy, but certainly not *that* easy.

>
> Cliff, do you have any references, or even personal experience to
> relate about anything on which you comment above?


I'm no expert on Python internals but it seems clear that an operation
such as [].append() is going to span multiple bytecode instructions. It
seems to me that if those instructions span the boundary defined by
sys.getcheckinterval() that the operation won't happen in a single
thread context switch (unless the interpreter has explicit code to keep
the entire operation within a single context).

I'm no expert at dis nor Python bytecode, but I'll give it a shot

>>> l = []
>>> dis.dis(l.append(1))

134 0 LOAD_GLOBAL 0 (findlabels)
3 LOAD_FAST 0 (code)
6 CALL_FUNCTION 1
9 STORE_FAST 5 (labels)


....
<snip dis spitting out over 500 lines of bytecode>
....

172 >> 503 PRINT_NEWLINE
504 JUMP_ABSOLUTE 33
>> 507 POP_TOP

508 POP_BLOCK
>> 509 LOAD_CONST 0 (None)

512 RETURN_VALUE
>>>



It looks fairly non-atomic to me. It's certainly smaller than the
default value for sys.getcheckinterval() (which defaults to 1000, iirc),
but that's hardly a guarantee that the operation won't cross the
boundary for a context switch (unless, as I mentioned above, the
interpreter has specific code to prevent the switch until the operation
is complete <shrug>).

I recall a similar discussion about three years ago on this list about
this very thing where people who know far more about it than I do flamed
it out a bit, but damned if I recall the outcome I do recall that it
didn't convince me to alter the approach I recommended to the OP.

> In my experience, and to my knowledge, Python threading *is*
> that easy (ignoring higher level issues such as race conditions
> and deadlocks and such), and the GIL *does* do exactly what Diez
> suggests, and you will *not* get tracebacks nor (again, ignoring
> higher level issues) mangled data.


Okay, to clarify, for the most part I *was* in fact referring to "higher
level issues". I doubt tracebacks or mangled data would occur simply
due to the operation's being non-atomic. However, if you have code that
say, checks for an item's existence in a list and then appends it if it
isn't there, it may cause the program to fail if another thread adds
that item between the time of the check and the time of the append.
This is what I was referring to by potential for mangled data and/or
tracebacks.

> You've tentatively upset my entire picture of the CPython (note,
> CPython only) interpreter's structure and concept. Please tell
> me you were going a little overboard to protect a possible
> newbie from himself or something.


Certainly protecting the newbie, but not going overboard, IMHO. I've
written quite a number of threaded Python apps and I religiously
acquire/release whenever dealing with mutable data structures (lists,
etc). To date this approach has served me well. I code fairly
conservatively when it comes to threads as I am *absolutely* certain
that debugging a broken threaded application is very near the bottom of
my list of favorite things

Regards,
Cliff

--
Cliff Wells <(E-Mail Removed)>

 
Reply With Quote
 
Duncan Booth
Guest
Posts: n/a
 
      10-13-2004
Cliff Wells wrote:

> I'm no expert at dis nor Python bytecode, but I'll give it a shot
>
>>>> l = []
>>>> dis.dis(l.append(1))

> 134 0 LOAD_GLOBAL 0 (findlabels)
> 3 LOAD_FAST 0 (code)
> 6 CALL_FUNCTION 1
> 9 STORE_FAST 5 (labels)
>
>
> ...
><snip dis spitting out over 500 lines of bytecode>
> ...
>
> 172 >> 503 PRINT_NEWLINE
> 504 JUMP_ABSOLUTE 33
> >> 507 POP_TOP

> 508 POP_BLOCK
> >> 509 LOAD_CONST 0 (None)

> 512 RETURN_VALUE
>>>>

>
>
> It looks fairly non-atomic to me.


The append method of a list returns None. dis.dis(None) disassembles the
code from the last traceback object, nothing at all to do with your
l.append(1) code.

Try this instead:

>>> def f():

l.append(1)


>>> dis.dis(f)

2 0 LOAD_GLOBAL 0 (l)
3 LOAD_ATTR 1 (append)
6 LOAD_CONST 1 (1)
9 CALL_FUNCTION 1
12 POP_TOP
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
 
Reply With Quote
 
Diez B. Roggisch
Guest
Posts: n/a
 
      10-13-2004
> Okay, to clarify, for the most part I *was* in fact referring to "higher
> level issues". I doubt tracebacks or mangled data would occur simply
> due to the operation's being non-atomic. However, if you have code that
> say, checks for an item's existence in a list and then appends it if it
> isn't there, it may cause the program to fail if another thread adds
> that item between the time of the check and the time of the append.
> This is what I was referring to by potential for mangled data and/or
> tracebacks.


_That_ of course I'm very well aware of - but to my expirience, with several
dozen threads appending to one list I never encountered a interpreter
failure. That is in contrast to java, where you get an
"ConcurrentModificationException" unless you don't ask specifically for a
synchronized variant of the collection of yours.


--
Regards,

Diez B. Roggisch
 
Reply With Quote
 
Cliff Wells
Guest
Posts: n/a
 
      10-13-2004
On Wed, 2004-10-13 at 14:03 +0000, Duncan Booth wrote:
> Cliff Wells wrote:
>
> > I'm no expert at dis nor Python bytecode, but I'll give it a shot
> >
> >>>> l = []
> >>>> dis.dis(l.append(1))

> > 134 0 LOAD_GLOBAL 0 (findlabels)
> > 3 LOAD_FAST 0 (code)
> > 6 CALL_FUNCTION 1
> > 9 STORE_FAST 5 (labels)
> >
> >
> > ...
> ><snip dis spitting out over 500 lines of bytecode>
> > ...
> >
> > 172 >> 503 PRINT_NEWLINE
> > 504 JUMP_ABSOLUTE 33
> > >> 507 POP_TOP

> > 508 POP_BLOCK
> > >> 509 LOAD_CONST 0 (None)

> > 512 RETURN_VALUE
> >>>>

> >
> >
> > It looks fairly non-atomic to me.

>
> The append method of a list returns None. dis.dis(None) disassembles the
> code from the last traceback object, nothing at all to do with your
> l.append(1) code.


Ah, thanks. I thought 500+ lines of bytecode was a bit excessive for a
simple append(), but didn't see any reason why. I saw the comment in
the docs about dis returning the last traceback if no argument was
provided but didn't see how that applied here.

>
> Try this instead:
>
> >>> def f():

> l.append(1)
>
>
> >>> dis.dis(f)

> 2 0 LOAD_GLOBAL 0 (l)
> 3 LOAD_ATTR 1 (append)
> 6 LOAD_CONST 1 (1)
> 9 CALL_FUNCTION 1
> 12 POP_TOP
> 13 LOAD_CONST 0 (None)
> 16 RETURN_VALUE


Much more reasonable. Still, I think my argument stands since this
appears non-atomic as well, although I do note this:

>>> l = []
>>> dis.dis(l.append)

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "/usr/lib/python2.3/dis.py", line 46, in dis
raise TypeError, \
TypeError: don't know how to disassemble builtin_function_or_method
objects
>>>


This suddenly gave me a smack on the head that list.append is
undoubtedly written in C and might, in fact, retain the GIL for the
duration of the function in which case the operation might, in fact, be
atomic (yes, I know that isn't necessarily what the above traceback was
saying, but it served as a clue-stick).

Still, despite the probability of being quite mistaken about the low-
level internals of the operation, I still stand by my assertion that not
using locks for mutable data is ill-advised at best, for the reasons I
outlined in my previous post (aside from the poorly executed
disassembly).

Regards,
Cliff

--
Cliff Wells <(E-Mail Removed)>

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Firefox locks up on first URL sometimes; Sometimes closes itself Jim Firefox 0 06-28-2005 01:42 PM
FireFox V1.0 locks up mosemoots Firefox 3 01-20-2005 02:02 PM
Wireless keyboard locks out the system!! =?Utf-8?B?RnJ1c3RyYXRlZA==?= Wireless Networking 0 09-06-2004 09:19 PM
File sharing locks up my laptop Tony Marston Wireless Networking 4 07-07-2004 08:56 PM
4006 SUP III locks up Flemming Haurum Cisco 0 11-01-2003 12:07 PM



Advertisments