Home arrow static arrow Java Programming [Archive] - Synchronize problem...please help...
Warning: Creating default object from empty value in /www/htdocs/w008deb8/wiki/components/com_staticxt/staticxt.php on line 51
Java Programming [Archive] - Synchronize problem...please help...
This topic has 46 replies on 4 pages.    1 | 2 | 3 | 4 | Next »

Posts:70
Registered: 11/5/02
Synchronize problem...please help...  
Jun 16, 2004 9:06 AM



 
My code:

public synchronized void doIt(String dummy)
{
Thread thread = new Thread(this);
thread.start();
}

public void run()
{
.... code to process
}

I have a method doIt() in a class (called class A). This method doIt() is called by pressing a button on a webpage. The method doIt() creates a new thread which then does all the processing needed and the method doIt() returns while the thread continues in the backgroundwiki/./. However, i dont want anyone else to call the method doIt() until the thread has finished running.

I need to have the processing in a separate thread in the doIt() method otherwise the user will have to wait several minutes before the next webpage loads up since it has to then wait for all the processing to finish before the method doIt() returns.

Now class A is application scoped (global scoped in Dynamo) so everyone is sharing this class.

I have put the synchronized keyword next to the method doIt(). This does not make no difference. If i click the webpage button from separate browser windows they both call doIt() and enter the method. I suspect this is happening because once the thread has been started, the method doIt() returns therefore releasing the lock. So how can i say keep the method locked until the thread finishes?

Thanks in advance...

 

Posts:205
Registered: 6/15/04
Re: Synchronize problem...please help...  
Jun 16, 2004 9:26 AM (reply 1 of 46)



 
You could implement class A thus
public class A{	public static boolean IS_FINISHED = falsepublic synchronized void doIt(String dummy)	{		if(!A.IS_FINISHED)		{			Thread thread = new Thread(this);			thread.start();		}	} 	public void run()	{		while(!A.IS_FINISHED)		{			// code to process		}		A.IS_FINISHED = true	}}
 

Posts:205
Registered: 6/15/04
Re: Synchronize problem...please help...  
Jun 16, 2004 9:29 AM (reply 2 of 46)



 
Sorry, but there are a couple of typos in that last posting
public class A{ public static boolean IS_FINISHED = false;     // only need to make this public if you want to set it from outside class A   // other class code, including constructor, etc.  public synchronized void doIt(String dummy)    // as a matter of curio, why pass a String when you're not using it? {  if(A.IS_FINISHED)                                   {   Thread thread = new Thread(this);   thread.start();  } }  public void run() {  while(!A.IS_FINISHED)  {   // code to process  }  A.IS_FINISHED = true }}
 

Posts:1,183
Registered: 1/23/02
Re: Synchronize problem...please help...  
Jun 16, 2004 9:31 AM (reply 3 of 46)



 
So how can i say keep the method locked until the thread finishes?

You can't, unless you block inside the method on thread.join(). But that would defeat the purpose of spawning the thread in the first place.

You can make the method ignore calls until the thread finishes.
class MyClass {    private Thread thread    public synchronized void doIt(String dummy)    {        if (thread != null && thread.isAlive()) {            return;        }        else {            thread = new Thread(this);            thread.start();        }    }    // ...}
 

Posts:70
Registered: 11/5/02
Re: Synchronize problem...please help...  
Jun 16, 2004 9:39 AM (reply 4 of 46)



 
Thanks for the suggestions...

what about if i synchronize the run() method. I tried it and it did work. Is this opening up a can of worms?
 

Posts:1,183
Registered: 1/23/02
Re: Synchronize problem...please help...  
Jun 16, 2004 9:45 AM (reply 5 of 46)



 
what about if i synchronize the run() method

Dirty but effective. I wouldn't do it. Especially if the worker threads access the fields of your object. The order in which things happen becomes very non-obvious.
 

Posts:334
Registered: 5/23/97
Re: Synchronize problem...please help...  
Jun 17, 2004 2:39 PM (reply 6 of 46)



 
what about if i synchronize the run() method

Dirty but effective. I wouldn't do it. Especially if
the worker threads access the fields of your object.
The order in which things happen becomes very
y non-obvious.

Why do you say dirty? II think it is a capability of the language and only dirty if implemented
poorly. For example, the previous example will eventually deadlock because of lack of notification.
Actually it makes waiting much simpler because you don't need the synch
statement and brackets inline. (for those who don't like the ancient Chinese art of TyPing ;)
Blame JPK for that bad joke BTW.

public synchronized void run()
{

notifyAll(); // Now it would be threadsafe, and without it will deadlock
}

Try using Thread.isAliave with a synchronized wait() set to 50-200 MS.
(Tweak as you like but you can tune it for best performance.)

////////////////// Example : save as ParentAndChild.java and compile

public class ParentAndChild implements Runnable{Thread task = null;Child child  = null; ParentAndChild(){   start();} public void start(){   task = new Thread(this);   task.start();} public void stop(){    child.task1 = null;    task          = null} public void run(){Thread controlThread = Thread.currentThread();   child = new Child();   child.start();   System.out.println("parent waiting for child");   while(!child.task1.isAlive())   {      synchronized(this)      {         try         {            wait(50);         }         catch(InterruptedException ie)         {         }         notifyAll();      }   }   System.out.println("Child is alive");           //---------------    while(controlThread == task)    {      synchronized(this)      {         try         {            wait(1000);         }         catch(InterruptedException ie)         {         }         notifyAll();      }      System.out.println("Parent");   }} public static void main(String args[]){ParentAndChild pac =  new ParentAndChild();   try   {      pac.task.join();    }   catch(InterruptedException ie)    {    }}    // Another yea old inner class class Child implements Runnable{Thread task1 = null;    //task1 avoids namespace conflict with parentpublic void start(){   task1=new Thread(this);   task1.start();} public void stop(){   task1 = null;} public void run(){Thread controlThread1 = Thread.currentThread();   while(controlThread1 == task1)   {      synchronized(this)      {         try         {            wait(1000);         }         catch(InterruptedException ie)         {         }      }      System.out.println("Child");   }}}}


// end example

Or you could poll either a boolean or a bitmask. Booleans are more efficient but
bitmasks allow you to poll multiple Threads at once, but that's another story..
Have fun!
(T)
 

Posts:1,183
Registered: 1/23/02
Re: Synchronize problem...please help...  
Jun 17, 2004 3:14 PM (reply 7 of 46)



 
Why do you say dirty? II think it is a capability of the language and only dirty if implemented poorly.

Yep, that's what I mean. It would be a poor implementation. There are better ways of making a piece of code single-threaded than synchronizing Runnable.run(). By better I mean less prone to misunderstanding by a reasonable person. If the Runnable also has state such code becomes prone to misunderstanding even by the person who writes it.

For example, the previous example will eventually deadlock because of lack of notification.

There is also lack of wait()***. Therefore notification is not needed.
 

Posts:334
Registered: 5/23/97
Re: Synchronize problem...please help...  
Jun 18, 2004 2:26 PM (reply 8 of 46)



 
OK I must confess that while I think everyone is entitled to my opinion,
no one is correct 100% of the time. However, I am not going to believe something
just because someone says it. So I am going to dig into this further and
explore the "facts."

Why do you say dirty? II think it is a capability
of the language and only dirty if implemented poorly.

Yep, that's what I mean. It would be a poor
implementation. There are better ways of making a
piece of code single-threaded than synchronizing
Runnable.run(). By better I mean less prone to
misunderstanding by a reasonable person.

I dunno... I fail to see where the misunderstanding is to anyone who can read.
//
As a matter of fact I usually do not use synchronized methods
except when starting and stopping, but that in fact goes back
to the old 1.1.5 JVM under Netscape... Which had its own unique set
of quirks. Lately I have unwound many of those as well.

If the
Runnable also has state such code becomes prone to
misunderstanding even by the person who writes it.

Heheh I would never confess in public to not understanding my own code
not that that has never happened OOps I recind that admission :)

For example, the previous example will eventually
deadlock because of lack of notification.

There is also lack of wait()***. Therefore
notification is not needed.

Consider that if another Thread could get blocked if it tries to
get the Monitor while the other thread in the synchronized method().
Would that Thread automatically be able to get the Monitor without being notified?

I can prove this; with this program.
//// synchronized method test.
public class SynchTest{static int id = 0; SynchTest(){int z;long maxIterations = 120;Caller c1 = new Caller();Caller c2 = new Caller();int iteration1 = 0;int iteration2  = 0;             // wait for threads to start   System.out.println("SynchTest()");   while(!c1.task.isAlive() && !c2.task.isAlive())   {      synchronized(this)      {       try{wait(100);}catch(InterruptedException ie){}      }      System.out.println("SynchTest waiting");   }   System.out.println("running");              //---------   for(z=0;z<maxIterations;z++)   {      synchronized(this)      {         try{wait(1000);}catch(InterruptedException ie){}      }            //----------      if(c1.iteration == iteration1 || c2.iteration == iteration2)      {         System.out.println("It deadlocked ");            System.exit(1);      }      System.out.println("c1="+c1.iteration+" c2="+c2.iteration);      iteration1 = c1.iteration;      iteration2 = c2.iteration;   }} public synchronized void synchedMethod(){ } public static void main(String args[]){   new SynchTest();}        //-----------class Caller implements Runnable{String msg = "";Thread task = null;int iteration = 0; Caller(){   start();} public void start(){   task = new Thread(this);   task.start();} public void stop(){   task = null;} public void run(){Thread controlThread = Thread.currentThread();   System.out.println("Caller running");   task.setName("Caller("+(id++)+")");   while(controlThread == task)   {      //System.out.println(" caller running "+this.toString());      synchedMethod();      iteration++;   }}} } //// end test

// Here is the exact Thread dump. It does take a while but it
// always deadlocks eventually.

Full thread dump Java HotSpot(TM) Client VM (1.4.2_04-b05 mixed mode):

"DestroyJavaVM" prio=5 tid=0x00034e90 nid=0x58c waiting on condition [0..7fad8]
"Caller(1)" prio=5 tid=0x00a0c148 nid=0x248 runnable [2cdf000..2cdfd8c]
at SynchTest.synchedMethod(SynchTest.java:46)
- waiting to lock <0x1002c2f0> (a SynchTest)
at SynchTest$Caller.run(SynchTest.java:83)
at java.lang.Thread.run(Unknown Source)

"Caller(0)" prio=5 tid=0x00a0bfe8 nid=0x4e4 waiting for monitor entry [2c9f000..2c9fd8c]
at SynchTest.synchedMethod(SynchTest.java:46)
- waiting to lock <0x1002c2f0> (a SynchTest)
at SynchTest$Caller.run(SynchTest.java:83)
at java.lang.Thread.run(Unknown Source)

"Signal Dispatcher" daemon prio=10 tid=0x009f53d8 nid=0x334 waiting on condition [0..0]

"Finalizer" daemon prio=9 tid=0x009bd2c8 nid=0x784 in Object.wait() [2b5f000..2b5fd8c]
at java.lang.Object.wait(Native Method)
- waiting on <0x10010498> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
- locked <0x10010498> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)

"Reference Handler" daemon prio=10 tid=0x009bbe98 nid=0x398 in Object.wait() [2b1f000..2b1fd8c]
at java.lang.Object.wait(Native Method)
- waiting on <0x10010388> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Unknown Source)
at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
- locked <0x10010388> (a java.lang.ref.Reference$Lock)

"VM Thread" prio=5 tid=0x009f36d0 nid=0x53c runnable

"VM Periodic Task Thread" prio=10 tid=0x009f7bf0 nid=0x250 waiting on condition
"Suspend Checker Thread" prio=10 tid=0x009f4940 nid=0x3c0 runnable

You can see that Caller0 and Caller1 are both waiting for the Monitor for(;;)
If you do proper notification however this never occurs.

I have to ask 2 questions.

1- Why would Sun make it a capability of the language if it is bad??
2- Why would Sun use it themselves if it is bad?

ie: from NIO.Channels .. This has very non typical constructor syntax BTW.
public synchronized void write(byte[] bs, int off, int len);
I always try to prove everything and leave nothing to chance.

Conclusion: I am not covinced using synchronized methods are dirty .
I must confess you made me question myself in this regard however :)

(T)

 

Posts:6,750
Registered: 1/25/04
Re: Synchronize problem...please help...  
Jun 18, 2004 2:40 PM (reply 9 of 46)



 
no one is correct 100% of the time. However, I am not
going to believe something
just because someone says it.
...
1- Why would Sun make it a capability of the language
if it is bad??
2- Why would Sun use it themselves if it is bad?

So are you believing something just because Sun said it, or do you think Sun is right 100% of the time? :-)
 

Posts:1,183
Registered: 1/23/02
Re: Synchronize problem...please help...  
Jun 18, 2004 2:58 PM (reply 10 of 46)



 
Consider that if another Thread could get blocked if it tries to get the Monitor while the other thread in the synchronized method(). Would that Thread automatically be able to get the Monitor without being notified?

Yes. Notification is required only to wake up a thread that is wait()***. Waiting for a monitor does not involve wait()***.

I'm not sure what your code is trying to demonstrate, but it exhibits a number of bad practices (like leaking object reference form a constructor and sharing variables between threads without synchronization), so I woundn't be surprised if it didn't do what you expected.

Conclusion: I am not covinced using synchronized methods are dirty .

They are not. Making Runnable.run() synchronized to solve OP's problem is. It's not the language feature that's dirty, it's how one (mis)uses it.
 

Posts:1,183
Registered: 1/23/02
Re: Synchronize problem...please help...  
Jun 18, 2004 2:59 PM (reply 11 of 46)



 
So are you believing something just because Sun said it, or do you think Sun is right 100% of the time? :-)

Dare you imply the contrary? :-)
 

Posts:1,183
Registered: 1/23/02
Re: Synchronize problem...please help...  
Jun 18, 2004 3:02 PM (reply 12 of 46)



 
tswain, please excuse the tone of my response, I'm trying to make the next "Arrogant Top Ten" list :-)
 

Posts:6,750
Registered: 1/25/04
Re: Synchronize problem...please help...  
Jun 18, 2004 3:30 PM (reply 13 of 46)



 
So are you believing something just because Sun said
it, or do you think Sun is right 100% of the time? :-)

Dare you imply the contrary? :-)

Imply? Ah, no, I'd better make it explicit: SUN IS NOT ALWAYS RIGHT. :-)
 

Posts:1,183
Registered: 1/23/02
Re: Synchronize problem...please help...  
Jun 18, 2004 3:48 PM (reply 14 of 46)



 
Imply? Ah, no, I'd better make it explicit: SUN IS NOT ALWAYS RIGHT. :-)

I'm reporting this as abuse.
 
This topic has 46 replies on 4 pages.    1 | 2 | 3 | 4 | Next »