multithreading-problem

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Diez B. Roggisch

    multithreading-problem

    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.Threa d(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
  • Manish Jethani

    #2
    Re: multithreading-problem

    Diez B. Roggisch wrote:
    [color=blue]
    > 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.Threa d(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.[/color]

    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

    Comment

    • Scott David Daniels

      #3
      Re: multithreading-problem

      Diez B. Roggisch wrote:[color=blue]
      > ...
      > for i in xrange(4):
      > thread = threading.Threa d(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....[/color]
      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:[color=blue]
      > ...
      > for i in xrange(4):
      > thread = threading.Threa d(target=lambda v=i: foo(v))
      > thread.start()
      > ...[/color]

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

      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
      Scott.Daniels@A cm.Org


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

      from __future__ import nested_scopes

      def curry(*_args, **_kwargs):
      """curry(f,<arg s>)(<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

      Comment

      • Diez B. Roggisch

        #4
        Re: multithreading-problem

        Manish Jethani wrote:
        [color=blue][color=green]
        >>
        >> 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.[/color]
        >
        > 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()[/color]

        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

        Comment

        • Diez B. Roggisch

          #5
          Re: multithreading-problem

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

          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

          Comment

          Working...