multithreading-problem

Discussion in 'Python' started by Diez B. Roggisch, Jul 27, 2003.

  1. Hi,

    I expirienced strange problems when using the module threading:

    class Bar:
    def __init__(_, arg):
    _.arg = arg
    def work(_):
    while 1:
    print _.arg

    def foo(arg):
    b = Bar(arg)
    b.work()

    for i in xrange(4):
    thread = threading.Thread(target=lambda : foo(i))
    thread.start()

    What I'd expect would be a sequence of prints like this
    1
    2
    3
    4
    1
    3
    4
    2

    What I actualy get is this:
    1
    4
    4
    4
    4
    1
    4
    4
    4

    Placing a time.sleep(3) after the thread.start() fixed things. So it appears
    that the curried lambda passed as target is somehow a reference equal for
    all four invocations.

    The used python is 2.2.<latest-cygwin>.

    Regards,

    Diez
    Diez B. Roggisch, Jul 27, 2003
    #1
    1. Advertising

  2. Diez B. Roggisch wrote:

    > Hi,
    >
    > I expirienced strange problems when using the module threading:
    >
    > class Bar:
    > def __init__(_, arg):
    > _.arg = arg
    > def work(_):
    > while 1:
    > print _.arg
    >
    > def foo(arg):
    > b = Bar(arg)
    > b.work()
    >
    > for i in xrange(4):
    > thread = threading.Thread(target=lambda : foo(i))
    > thread.start()
    >
    > What I'd expect would be a sequence of prints like this
    > 1
    > 2
    > 3
    > 4
    > 1
    > 3
    > 4
    > 2
    >
    > What I actualy get is this:
    > 1
    > 4
    > 4
    > 4
    > 4
    > 1
    > 4
    > 4
    > 4
    >
    > Placing a time.sleep(3) after the thread.start() fixed things. So it appears
    > that the curried lambda passed as target is somehow a reference equal for
    > all four invocations.


    No, I don't believe it to be true. It's probably just that the
    other threads aren't getting a chance to run. Consider
    time.sleep(0) in the while loop in work()

    -Manish

    --
    Manish Jethani (manish.j at gmx.net)
    phone (work) +91-80-51073488
    Manish Jethani, Jul 27, 2003
    #2
    1. Advertising

  3. Diez B. Roggisch wrote:
    > ...
    > for i in xrange(4):
    > thread = threading.Thread(target=lambda : foo(i))
    > thread.start()
    > ... So it appears that the curried lambda passed as target is
    > somehow a reference equal for all four invocations....

    This is why the "curry" recipe dances more jig than you have.
    the lambda-expression that you've passed in did not do any
    value-capture. The smallest fix is:
    > ...
    > for i in xrange(4):
    > thread = threading.Thread(target=lambda v=i: foo(v))
    > thread.start()
    > ...


    With curry from the Python Cookbook (or as below), I'd write:
    > ...
    > for i in xrange(4):
    > thread = threading.Thread(target=curry(foo, i))
    > thread.start()
    > ...


    The problem is that your lambda expression looks up "i" at function
    evaluation time (when target is called), not when you assign the
    target function for the thread.

    -Scott David Daniels



    =============================
    for 2.2 I define curry as:

    from __future__ import nested_scopes

    def curry(*_args, **_kwargs):
    """curry(f,<args>)(<more>) == f(<args>, <more>) (roughly).

    keyword args in the curry call can be overridden by keyword args
    in the later call; curry can be used to change defaults.
    """
    def result(*__args, **__kwargs):
    if _kwargs and __kwargs:
    kwargs = _kwargs.copy()
    kwargs.update(__kwargs)
    else:
    kwargs = _kwargs or __kwargs
    return _args[0](*(_args[1:]+__args), **kwargs)
    return result
    Scott David Daniels, Jul 27, 2003
    #3
  4. Manish Jethani wrote:

    >>
    >> Placing a time.sleep(3) after the thread.start() fixed things. So it
    >> appears that the curried lambda passed as target is somehow a reference
    >> equal for all four invocations.

    >
    > No, I don't believe it to be true. It's probably just that the
    > other threads aren't getting a chance to run. Consider
    > time.sleep(0) in the while loop in work()


    No, they all run - just a few of them have the same parameters. In my real
    app, all of them do some work, which takes an individual amount of time. In
    the main-thread I wait for all of them to be terminated, and while doing
    that print how much are still running. All this works as expected. The only
    thing not working is the parameter passing.

    Diez
    Diez B. Roggisch, Jul 27, 2003
    #4
  5. > The problem is that your lambda expression looks up "i" at function
    > evaluation time (when target is called), not when you assign the
    > target function for the thread.


    Ah, ok. That makes sense. Where do I find this curry-function, only in the
    book? It appears not to be a standard function.

    Regards, Diez
    Diez B. Roggisch, Jul 27, 2003
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. insomniac

    ASP.Net 2.0 Multithreading Problem

    insomniac, Apr 27, 2006, in forum: ASP .Net
    Replies:
    2
    Views:
    2,688
    insomniac
    Apr 27, 2006
  2. Lee Garrington

    Multithreading beginner problem

    Lee Garrington, Dec 22, 2003, in forum: C++
    Replies:
    1
    Views:
    548
    Thomas Matthews
    Dec 22, 2003
  3. Replies:
    1
    Views:
    3,124
    bruce barker \(sqlwork.com\)
    May 11, 2006
  4. abhinav

    Python multithreading problem

    abhinav, Mar 26, 2006, in forum: Python
    Replies:
    3
    Views:
    366
    abhinav
    Mar 27, 2006
  5. Vera
    Replies:
    5
    Views:
    821
Loading...

Share This Page