1 2 3 Previous Next 35 Replies Latest reply: Jan 16, 2009 3:34 PM by 807589 RSS

    Sharing with Concurrency

    807589
      I have a simple setup. I am stuck on how to "share" my lock with another thread.

      My setup is: I have a "processor" thread that gobbles up tasks. It is always running.
      I also have a component that displays the result (an image). Im using a RentrantLock. If tryLock() fails
      the component just draws a wait screen.

      My main problem is: I dont know how to guarantee a repaint when a task is done.
      I cant call invokeAndWait because that would cause a deadlock. The repaint request is
      on the EDT (a different thread then the processor) and it would never get to enter the lock
      to draw the image.

      This is my pseudo-code:
      screen extends jcomponent{
      paintComponent{
      
      boolean drawn = processor.drawImage(gfx)
      if(!drawn){ draw wait screen } 
      
      }
      }
      
      processor{
      
      RentrantLock lock
      
      drawImage(gfx){
      if(lock.tryLock()){
      gfx.drawImage(image)
      return true
      }
      return false
      }
      
      do(task){
      lock.lock()
      process(task)
      }
      
      private process(task){
      // do task
      // how do i guarantee a repaint here?
      }
      
      }
      My humble solution would be to always allow the waiting EDT to preempt all other waiting threads.
      I see RentrantLock has a getWaitingThreads() method. I could just search the collection for the EDT.
      How do I write the preempting code?

      Edit: Actually that wouldnt work. The EDT is never waiting for a lock. It is using tryLock. I would love any suggestions!
        • 1. Re: Sharing with Concurrency
          r035198x
          A silly question just to be sure.
          You are using the SwingWorker class for this right?
          • 2. Re: Sharing with Concurrency
            807589
            As I recall from using SwingWorker in the past, it is for one off background tasks.
            I have a process thread that is ALWAYS running. It is always processing tasks
            and I need to have thread-safe access to an image it manages.
            • 3. Re: Sharing with Concurrency
              r035198x
              TuringPest wrote:
              As I recall from using SwingWorker in the past, it is for one off background tasks.
              Not necessarily (as far as I understand it at least). Your task is always running so you don't need to use done method.
              You'll just be constantly publish(ing) results to the interface.
              • 4. Re: Sharing with Concurrency
                807589
                SwingWorker is not what im looking for. Imagine my process thread is an email messaging system,
                or an air traffic control system or something. Just because a component needs to access one thing
                in the system doesnt mean the whole system should be a SwingWorker.

                Essentially, in the locked "process(task)" method of my system, I need to pause and share something
                with a component.
                • 5. Re: Sharing with Concurrency
                  r035198x
                  Sorry for being off then. Wouldn't invokeLater() wait until the EDT is able to enter the lock?
                  • 6. Re: Sharing with Concurrency
                    807589
                    TuringPest wrote:
                    Essentially, in the locked "process(task)" method of my system, I need to pause and share something
                    with a component.
                    Why are you holding the lock for the whole process task, if you want other threads access to the data the lock protects?
                    process () {
                       for (;;) {
                          lock.lock();
                          try {
                            process some data 
                          } finally {
                            lock.unlock();
                          }
                          
                          tell observers to update
                       }
                    }
                    • 7. Re: Sharing with Concurrency
                      807589
                      Sorry for being off then.
                      not at all. dont worry about it.
                      Wouldn't invokeLater() wait until the EDT is able to enter the lock?
                      no because im using tryLock to prevent the gui from freezing up.

                      i have this system that processes tasks from different threads that are queued.
                      because several tasks require thread-safe operation on an image (and its too big
                      to copy), i guard access to it. i dont want any GUIs reliant on that image to become
                      unresponsive so i use tryLock().

                      however, when certain tasks are done, i want to guarantee the image is drawn.

                      display{
                      if tryLock()
                      // do something
                      else
                      // ignore
                      }

                      process{

                      lock()
                      // do task
                      // ## repaint here, but access is locked (the tryLock in display will fail) ##
                      unlock()

                      }

                      In the ## section if i call invokeLater() then the repaint call will be queued, flow will continue and
                      unlock() will be called and another task from the
                      queue will lock access again. so when repaint is finally called, access could still be blocked, but by a
                      different task. if i call invokeAndWait then the repaint will call tryLock which will fail and then the task will
                      unlock - without actually haven drawn anything.

                      Im thinking I could use a flag? Like this:

                      display{

                      if swingutilities.isEDT && flag.isSet || tryLock()
                      // do something
                      else
                      // ignore
                      }

                      process{

                      lock()
                      // do task
                      // set flag
                      // invokeAndWait
                      // unset flag
                      unlock()

                      }

                      Does that seem reasonable?
                      • 8. Re: Sharing with Concurrency
                        r035198x
                        Why not

                        lock()
                        // do task
                        //
                        //unlock()
                        // invokeAndWait
                        //

                        ?
                        Then you don't have to sneak the EDT in when there is a lock
                        • 9. Re: Sharing with Concurrency
                          807589
                          r035198x wrote:
                          Why not
                          //unlock()
                          // invokeAndWait
                          Then you don't have to sneak the EDT in when there is a lock
                          The unlock() awakens other threads waiting on lock() right?
                          Would it be possible for another thread to gain the lock between unlock and invokeandwait?
                          If not, then thats the solution. Being up at 4 am sure makes your brain stop working.
                          • 10. Re: Sharing with Concurrency
                            r035198x
                            TuringPest wrote:
                            r035198x wrote:
                            Why not
                            //unlock()
                            // invokeAndWait
                            Then you don't have to sneak the EDT in when there is a lock
                            The unlock() awakens other threads waiting on lock() right?
                            Would it be possible for another thread to gain the lock between unlock and invokeandwait?
                            If not, then thats the solution. Being up at 4 am sure makes your brain stop working.
                            Unfortunately I think it's possible for other threads to get that lock.
                            • 11. Re: Sharing with Concurrency
                              791266
                              My humble solution would be to always allow the waiting EDT to preempt all other waiting threads.
                              I see RentrantLock has a getWaitingThreads() method. I could just search the collection for the EDT.
                              How do I write the preempting code?

                              Edit: Actually that wouldnt work. The EDT is never waiting for a lock. It is using tryLock. I would love any suggestions!
                              What are you saying? Many threads are waiting and you want a certain thread to get the lock when you release it?
                              • 12. Re: Sharing with Concurrency
                                r035198x
                                Sounds paradoxial. Well the flag approach could work. Set a flag called updating before calling unlock and InvokeAndWait.
                                when other threads are requesting the lock check updating. If updating then only allow access if thread is EDT.
                                • 13. Re: Sharing with Concurrency
                                  807589
                                  r035198x wrote:
                                  TuringPest wrote:
                                  r035198x wrote:
                                  Why not
                                  //unlock()
                                  // invokeAndWait
                                  Then you don't have to sneak the EDT in when there is a lock
                                  The unlock() awakens other threads waiting on lock() right?
                                  Would it be possible for another thread to gain the lock between unlock and invokeandwait?
                                  If not, then thats the solution. Being up at 4 am sure makes your brain stop working.
                                  Unfortunately I think it's possible for other threads to get that lock.
                                  Not with the design you've posted - there are only two threads with access to the object the lock is a field of, and if the process thread releases the lock then waits for the event dispatch thread to complete running a runnable, then there isn't anything else that can happen.
                                  • 14. Re: Sharing with Concurrency
                                    r035198x
                                    >
                                    Not with the design you've posted - there are only two threads with access to the object the lock is a field of, and if the process thread releases the lock then waits for the event dispatch thread to complete running a runnable, then there isn't anything else that can happen.
                                    Yep we threw that one away (See Pest's reply to 8 and my post after that.)
                                    1 2 3 Previous Next