#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2005
    Posts
    418
    Rep Power
    20

    Threads/synchronization


    Hi,
    I am new into multi threaded programming and I cant seem to understand a few things. Let's say I have a class 'someClass' which starts two threads that should write a 0 and 1 in turns. So the first thread should write a zero, then the second a one then the first a zero again then the second a one, etc. (01010101 is valid but not 011110101 or 1010101010)

    java Code:
    public class someClass{
     
    	someClass(  ) {
    	}
     
    	public static void main( String argv[] ){
    		someClassThread t1 = new someClassThread(0);
    		someClassThread t2 = new someClassThread(1);
    		t1.start();
    		t2.start();
    	}
    }

    And:
    java Code:
    import java.lang.*;
    import java.io.*;
     
     
    public class someClassThread extends Thread {
    	PrintStream out = new PrintStream( System.out );
    	int threadId, turn;
     
    	someClassThread( int threadId ) {
    		this.threadId = threadId;
    	}
     
     
    	private void printMethod( String s ){
    		for( int i=0; i<s.length(); i++ ){
    			out.printf( "%c", s.charAt(i) );
    		}	
    	}
     
    	public void run() {
    		String s;
    		if( threadId == 0 ){
    			s = "0";
    		} else{
    			s = "1";
    		}
     
     
    		if( threadId == 0 ){
    			try{
    				for ( int i=0;i<10;i++ ){
    					synchronized( this ){
    						while( turn == 1 ){
    							this.wait();						
    						}
    						printMethod(s);
    						turn = 1;
    						this.notifyAll();
    					}
    				}
    			} catch( Exception e ){
    				System.out.println("Message "+e.getMessage());
    				System.exit(1);
    			}
    		} 
    		else if( threadId == 1 ){
    			try{
    				for ( int i=0;i<10;i++ ){
    					synchronized( this ){
    						while( turn == 0 ){
    							this.wait();
    						}	
    						printMethod(s);
    						turn = 0;
    						this.notifyAll();
    					}
    				}
    			} catch( Exception e ){
    				System.out.println("Message "+e.getMessage());
    				System.exit(1);
    			}
    		}
    	}
    }


    What I tried is to use the turn variable (this is shared between the threads right?) to indicate who's turn it is and if its not the thread's turn then he blocks waiting for a notify(all) call.

    However, I wasn't sure on what to call the synchronized block. I tried synchronized( this ) but I think this is not correct. I know I should put the object to lock on between the synchronized parenthesis but what is that in this case? Also I dont know on which object to call wait() and notifyAll() it should be the same object as what you specify for the synchronized block right?

    And finaly, I specify a thread ID but I think the threadId variable is shared between the threads, so the second thread probably overwrites the threadId. How is this usually done?

    I hope anyone can clear some things up for me. Don't hold back telling me i'm doing it all wrong or I am taking a weird approach on this.

    Thanks in advance

    Stefan1
    Last edited by Stefan1; September 21st, 2012 at 10:28 AM. Reason: Code didn't compile without errors, now it should.
  2. #2
  3. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,724
    Rep Power
    348
    The posted code does not compile without errors.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2005
    Posts
    418
    Rep Power
    20
    Oh sorry, this code is really just a stripped down version of what I actually want to know, but I didn't test the code, sorry for that. Now I changed it in the original post and below i posted it again.

    Hope anyone can still help me out.

    java Code:
    public class someClass{
     
    	someClass(  ) {
    	}
     
    	public static void main( String argv[] ){
    		someClassThread t1 = new someClassThread(0);
    		someClassThread t2 = new someClassThread(1);
    		t1.start();
    		t2.start();
    	}
    }

    java Code:
    import java.lang.*;
    import java.io.*;
     
     
    public class someClassThread extends Thread {
    	PrintStream out = new PrintStream( System.out );
    	int threadId, turn;
     
    	someClassThread( int threadId ) {
    		this.threadId = threadId;
    	}
     
     
    	private void printMethod( String s ){
    		for( int i=0; i<s.length(); i++ ){
    			out.printf( "%c", s.charAt(i) );
    		}	
    	}
     
    	public void run() {
    		String s;
    		if( threadId == 0 ){
    			s = "0";
    		} else{
    			s = "1";
    		}
     
     
    		if( threadId == 0 ){
    			try{
    				for ( int i=0;i<10;i++ ){
    					synchronized( this ){
    						while( turn == 1 ){
    							this.wait();						
    						}
    						printMethod(s);
    						turn = 1;
    						this.notifyAll();
    					}
    				}
    			} catch( Exception e ){
    				System.out.println("Message "+e.getMessage());
    				System.exit(1);
    			}
    		} 
    		else if( threadId == 1 ){
    			try{
    				for ( int i=0;i<10;i++ ){
    					synchronized( this ){
    						while( turn == 0 ){
    							this.wait();
    						}	
    						printMethod(s);
    						turn = 0;
    						this.notifyAll();
    					}
    				}
    			} catch( Exception e ){
    				System.out.println("Message "+e.getMessage());
    				System.exit(1);
    			}
    		}
    	}
    }
  6. #4
  7. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,724
    Rep Power
    348
    One problem I see is the synchronze() statement is for different class objects. To work it must be on the same object.
    One way would be to define an object that both threads can synchronize on and pass it to the constructors.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2005
    Posts
    418
    Rep Power
    20
    Thanks for the reply.

    Do you mean like I did below, where I passed 'this' as argument to the someClassThread constructor and then that obj is used to synchronize on?

    java Code:
    public class someClass{
     
    	someClass(  ) {
    	}
     
    	private void start(){
    		someClassThread t1 = new someClassThread(0, this );
    		someClassThread t2 = new someClassThread(1, this );
    		t1.start();
    		t2.start();
    	}
     
     
    	public static void main( String argv[] ){
    		new someClass().start();
    	}
    }

    java Code:
    import java.lang.*;
    import java.io.*;
     
     
    public class someClassThread extends Thread {
    	PrintStream out = new PrintStream( System.out );
    	int threadId, turn;
    	someClass obj;
     
    	someClassThread( int threadId, someClass obj ) {
    		this.threadId = threadId;
    		this.obj = obj;
    	}
     
     
    	private void printMethod( String s ){
    		for( int i=0; i<s.length(); i++ ){
    			out.printf( "%c", s.charAt(i) );
    		}	
    	}
     
    	public void run() {
    		String s;
    		if( threadId == 0 ){
    			s = "0";
    		} else{
    			s = "1";
    		}
     
     
    		if( threadId == 0 ){
    			try{
    				for ( int i=0;i<10;i++ ){
    					synchronized( obj ){
    						while( turn == 1 ){
    							obj.wait();						
    						}
    						printMethod(s);
    						turn = 1;
    						obj.notifyAll();
    					}
    				}
    			} catch( Exception e ){
    				System.out.println("Message "+e.getMessage());
    				System.exit(1);
    			}
    		} 
    		else if( threadId == 1 ){
    			try{
    				for ( int i=0;i<10;i++ ){
    					synchronized( obj ){
    						while( turn == 0 ){
    							obj.wait();
    						}	
    						printMethod(s);
    						turn = 0;
    						obj.notifyAll();
    					}
    				}
    			} catch( Exception e ){
    				System.out.println("Message "+e.getMessage());
    				System.exit(1);
    			}
    		}
    	}
    }


    If that was the problem then there must be another problem as it still isn't working.
  10. #6
  11. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,724
    Rep Power
    348
    That was an error I saw. I haven't tried debugging it yet.

    Try debugging the code by adding lots of println statements to show where the code is executing. That should show you where the code is not doing what you expect.

    The code is way too complicated.
    Why not print the threadId value directly using println(threadId) instead of using s?
    Why test which threadId?
    What is turn for?

    Get rid of all that stuff. Make the code take turns.
    Last edited by NormR; September 21st, 2012 at 11:34 AM.
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2005
    Posts
    418
    Rep Power
    20
    Originally Posted by NormR
    The code is way too complicated.
    Why not print the threadId value directly using println(threadId) instead of using s?
    Why test which threadId?
    What is turn for?
    Get rid of all that stuff. Make the code take turns.
    It is not about writing the threadId it is about the printMethod being executed in turns. It doesn't really matter what it prints as long as the threads take turns in calling the method.

    The reason I do all that stuff is because threads run simultaneously. I tried to use a condition variable technique such as can be done in C programming.

    The turn variable specifies which thread's turn it is. After thread A is done with the printMethod() then it sets the turn to thread B and then signals that thread to wakeup and proceed. Because the turn variable is shared between the two threads, thread A can not proceed untill thread B confirms that it is thread A's turn again (it does so by setting turn to 0 and signalling it to wake up). But maybe it can be done with only one turn variable, i'm not sure.

    However How do I set the threadId without overwriting the other thread's id?
    Last edited by Stefan1; September 21st, 2012 at 12:23 PM.
  14. #8
  15. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,724
    Rep Power
    348
    turn variable specifies which thread's turn it is
    That is handled by the JVM. It will give control to a thread when the conditions are right for that thread to execute: not waiting or held up by a synchronized block.
    When the code is executing, it knows that it is its turn.

    the turn variable is shared between the two threads
    How is that done? Each object has its own copy of the variable.

    Go to a simpler design. Using synchronized, wait and notify how can the two threads take turns?

    How do I set the threadId without overwriting the other thread's id?
    Each class object has its own copy.
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2005
    Posts
    418
    Rep Power
    20
    Hmm, I was under the illusion that different threads shared the same variables that are global in the class which extends Thread. So in my example I thought turn was being shared among all threads. I think I read something about instance variables being shared, but I did some tests and indeed they keep their own value.

    Its kind of hard to find good information on this. How can you share a variable between two threads then? Let's say a variable that both threads are able to access/increase/read. This is just out of curiosity not specifically aimed at the problem I am solving.

    I still can't seem to figure out how to do it with only synchronize, wait and notifyAll() I tried a few things but they all seem flawed.
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2005
    Posts
    418
    Rep Power
    20
    Ok I have it working now, but it doesn't really seem pretty in my opinion :P

    I still don't get a few things or am not sure about how it works. I would really appreciate it if anyone could answer the following questions for me:

    1. In my code i us the object that created the threads as argument for the synchronize() block. Is it normal to it like this? Can it be any object as long as the different threads use the same object for the synchronized blocks?

    2. Is it correct that when you call "wait()" that other threads can enter the synchronized block?

    3. Does wait() need to be called on the same object as is used in the synchronized block? Like: synchronize( someObj ){ someObj.wait() } ?

    4. Do I really need to check the threadId in order for this to work? I could let both threads run the same code except printing a different string, but this wouldn't work with how I am doing it as I must enforce that the thread that enters the synchronized block first is the thread that writes 'AB' and not the thread that writes 'CD'. I could think of a way where I dont check the threadId, but then I would need a variable that is shared between two threads.

    5. How do you share a variable between two threads so that they can both write and read it? Doesn't matter that there might be race conditions then.

    java Code:
    class syn2{
    	syn2() {
    	}
     
    	private void start(){
    		Syn2Thread t1 = new Syn2Thread( 0, this );
    		Syn2Thread t2 = new Syn2Thread( 1, this );
    		t1.start();
    		t2.start();
    	}
     
     
    	public static void main( String argv[] ){
    		new syn2().start();
    	}
    }


    java Code:
    import java.lang.*;
    import java.io.*;
     
     
    public class Syn2Thread extends Thread {
    	int threadId;
    	PrintStream out = new PrintStream( System.out );
    	syn2 obj;
     
     
    	Syn2Thread( int threadId, syn2 obj ) {
    		this.threadId = threadId;
    		this.obj = obj;
    	}
     
     
    	private void display( String s ){
    		for( int i=0; i<s.length(); i++ ){
    			out.printf( "%c", s.charAt(i) );
    		}
     
    	}
     
    	public void run() {
    		String s;
    		if( threadId == 0 ){
    			this.threadId = 5;
    			s = "ab";
    		} else{
    			s = "cd\n";
    		}
     
     
    		if( threadId == 0 ){
    			try{
    				for ( int i=0;i<10;i++ ){
    					synchronized( this.obj ){
    						display(s);
        	                this.obj.notifyAll();
       						this.obj.wait();
    					}
    				}	
    				synchronized( this.obj ){
    					this.obj.notifyAll();
    				}		
    			} catch( Exception e ){
    				System.out.println("Message "+e.getMessage());
    				System.exit(1);
    			}
    		} else{
    			try{
    				for ( int i=0;i<10;i++ ){
    					synchronized( this.obj ){
    						display(s);
    		                this.obj.notifyAll();
    						this.obj.wait();
    					}
    				}
    				synchronized( this.obj ){
    					this.obj.notifyAll();
    				}
     
    			} catch( Exception e ){
    				System.out.println("Message "+e.getMessage());
    				System.exit(1);
    			}
    		}
    	}
    }


    Thanks for the help!
  20. #11
  21. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,724
    Rep Power
    348
    1. In my code i us the object that created the threads as argument for the synchronize() block. Is it normal to it like this? Can it be any object as long as the different threads use the same object for the synchronized blocks?
    You can use any object. this would be OK, or Object monitor = new Object();
    2. Is it correct that when you call "wait()" that other threads can enter the synchronized block?
    Yes
    3. Does wait() need to be called on the same object as is used in the synchronized block? Like: synchronize( someObj ){ someObj.wait() } ?
    Did you read the API doc for the wait() method? "The current thread must own this object's monitor."
    4. Do I really need to check the threadId in order for this to work? I could let both threads run the same code except printing a different string, but this wouldn't work with how I am doing it as I must enforce that the thread that enters the synchronized block first is the thread that writes 'AB' and not the thread that writes 'CD'. I could think of a way where I dont check the threadId, but then I would need a variable that is shared between two threads.
    Each object has its own threadId variable. To have more than one thread run the same code, you need to create ONLY ONE object. This code creates two objects
    5. How do you share a variable between two threads so that they can both write and read it? Doesn't matter that there might be race conditions then.
    Have both threads run the same code, not separate versions.

    Change the class to extend Runnable, create ONE instance of the class and pass it to two instances of the Thread class.

IMN logo majestic logo threadwatch logo seochat tools logo