aspose file tools*
The moose likes Threads and Synchronization and the fly likes Properly Synchronizing a Block of Code Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Java 8 in Action this week in the Java 8 forum!
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "Properly Synchronizing a Block of Code" Watch "Properly Synchronizing a Block of Code" New topic
Author

Properly Synchronizing a Block of Code

David Dobor
Greenhorn

Joined: Feb 21, 2012
Posts: 6

Hello,

This may be a basic thread synchronization question for an experienced Java programmer, but here it is:

I am attempting to synchronize a block of code. This block of code will take a character, say 'A', and print it five times, followed by a space. I'd like to be able to call this block of code again by passing it another character 'B', then 'C', so that the final output is "AAAAA BBBBB CCCCC ". (Or, if it's "BBBBB AAAAA CCCCC ", or some other permutation of the blocks themselves, I wouldn't be terribly disappointed.)

I wrote the following program to do this. By synchronizing and overriding the run() method in my LetterPrinter class (which extends the Thread class), I expected to get the desired output. However, if I run this program a few times, I do get outputs that intersperse the letttes, i.e. outputs like this: "AAAAA CCCCBBBBB C ".

I thought that by synchronizing the run method, I'd lock the Thread that's printing these characters, so that no other Thread could butt in to disturb the Thread doing the printing.

Does anybody know what the issue is and how to fix it?

(I suspect it's a real quick and basic fix).

Thanks very much!

Cheers, Dave.

Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18150
    
    8

David Dobor wrote:I thought that by synchronizing the run method, I'd lock the Thread that's printing these characters


Yes, that's exactly what you did. Each Thread acquires a lock on itself.

so that no other Thread could butt in to disturb the Thread doing the printing.


But that doesn't follow. If Thread A has a lock on itself, and Thread B has a lock on itself, then neither of them is preventing the other from doing anything at all. If you wanted Thread A to lock out Thread B while Thread A was executing a critical section of code, then they both need to use the same object to lock on.

So instead of just "synchronized" you need "synchronized(X)" where X is a reference to some common object which doesn't belong to any of the threads.
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Also, don't get into the habit of extending Thread. Implement Runnable instead. You're not creating a specialized type of Thread; you're just creating a task that is able to be Run(n) in its own thread.
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Paul Clapham wrote:
David Dobor wrote:I thought that by synchronizing the run method, I'd lock the Thread that's printing these characters


Yes, that's exactly what you did. Each Thread acquires a lock on itself.


And in fact, to be more precise, and to cover the general case, when you declare a an instance method (non-static method) synchronized, it's the same as if the body of the method was inside a synchronized (this) { ... } block. The only reason you "locked a Thread" (reall, you obtained the Thread object's lock, you didn't "lock" the object per se) is because in this case it happened to be a Thread's method that you synchronized. (And in fact, it wasn't even simply a Thread, but your subclass of Thread.) If that method had been in class Foo, then you would have "locked" (obtained the lock for) that Foo object, without regard to any Thread object or thread of execution.
David Dobor
Greenhorn

Joined: Feb 21, 2012
Posts: 6

I see. Thank you very, very much! I am beginning to see how this works.
David Dobor
Greenhorn

Joined: Feb 21, 2012
Posts: 6

Paul Clapham wrote:
So instead of just "synchronized" you need "synchronized(X)" where X is a reference to some common object which doesn't belong to any of the threads.



By the way, following your suggestion I simply changed the run() method in my Thread to the following:

Simply making an immutable String object withing quotes and giving it to synchronized(X) - instead of manually creating a separate object (i.e. by saying: new SomeObject() ) and passing a reference to it to these Threads - seems to work. I don't know whether this is generally considered to be a good practice or not by seasoned Java programmers (I have not yet seen any code that does this) but it seems to do the trick for my little program.

Thanks again.

D.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18150
    
    8

David Dobor wrote:I don't know whether this is generally considered to be a good practice or not by seasoned Java programmers (I have not yet seen any code that does this) but it seems to do the trick for my little program.


I wouldn't consider it to be a good practice. I would prefer to use a lock object which is restricted to the LetterPrinter class, rather than one which could be carelessly used by somebody else who was adding more synchronization-requiring code to what you wrote. Like this:
David Dobor
Greenhorn

Joined: Feb 21, 2012
Posts: 6

Paul Clapham wrote:
David Dobor wrote:I don't know whether this is generally considered to be a good practice or not by seasoned Java programmers (I have not yet seen any code that does this) but it seems to do the trick for my little program.


I wouldn't consider it to be a good practice. I would prefer to use a lock object which is restricted to the LetterPrinter class, rather than one which could be carelessly used by somebody else who was adding more synchronization-requiring code to what you wrote. Like this:



Yes, thanks again, that is how I understood your initial posting.

(And I realize that declaring the locker Object static is crucial here: it ensures that only one instance of the locker Object is being shared by all the different instances of the LetterPrinter class.)
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18150
    
    8

Beginners often seem to think that String is some kind of special class. Often they will try to stuff all kinds of things into a single String rather then creating a class specifically to hold those things. In your case you decided a String would work as a lock object, whereas the purpose of String is only to contain a smallish amount of text. But it's Object whose instances have no purpose except to exist, and that's why I chose an Object to lock on.

David Dobor wrote:(And I realize that declaring the locker Object static is crucial here: it ensures that only one instance of the locker Object is being shared by all the different instances of the LetterPrinter class.)


Yes, you have that right.
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

David Dobor wrote:
(And I realize that declaring the locker Object static is crucial here


Couple of minor quibbles:

1) It's the variable that's static, not the object. Objects don't have the property of being static or non-static. There's no such thing as a static object, or even a non-static one, just as there are neither tall nor short objects in Java.

2) Strictly speaking, you don't have to use a static variable for the lock, but in this example it's the most sensible and simplest approach.
David Dobor
Greenhorn

Joined: Feb 21, 2012
Posts: 6

Jeff Verdegan wrote:
David Dobor wrote:
(And I realize that declaring the locker Object static is crucial here


Couple of minor quibbles:

1) It's the variable that's static, not the object. Objects don't have the property of being static or non-static. There's no such thing as a static object, or even a non-static one, just as there are neither tall nor short objects in Java.

2) Strictly speaking, you don't have to use a static variable for the lock, but in this example it's the most sensible and simplest approach.


Yes, thank you, I realize that:

1) I should have said: "It's a static variable that holds a reference to an Object of class Object". I guess it pays to forego of a bit of informality for the sake of greater clarity. I'll get the proper Java lingo down on one of these sunny days.

2) Yes, using a static variable for the lock is not necessary, as the following version of my program demonstrates. Unlike the initial version, this one also takes into account your suggestion of not getting into the habit of extending the Thread class directly, but rather implementing a Runnable interface, passing it to a constructor of a Thread object, and then starting the Thread.

Well, without much further talk, here's another version that also works. (It my be excessively commented, but clearer to anyone reading it, I hope):
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

David Dobor wrote:
1) I should have said: "It's a static variable that holds a reference to an Object of class Object". I guess it pays to forego of a bit of informality for the sake of greater clarity. I'll get the proper Java lingo down on one of these sunny days.

2) Yes, using a static variable for the lock is not necessary, as the following version of my program demonstrates. Unlike the initial version, this one also takes into account your suggestion of not getting into the habit of extending the Thread class directly, but rather implementing a Runnable interface, passing it to a constructor of a Thread object, and then starting the Thread.


In both these cases, if you're talking to someone that you know has a certain level of understanding, it's fine to go for the less accurate shortcut. I just try to be as precise as possible here, since I don't usually know where the OP's knowledge lies and where there are gaps, and I don't want to inadvertently give bad information.
David Dobor
Greenhorn

Joined: Feb 21, 2012
Posts: 6

Jeff Verdegan wrote:
In both these cases, if you're talking to someone that you know has a certain level of understanding, it's fine to go for the less accurate shortcut. I just try to be as precise as possible here, since I don't usually know where the OP's knowledge lies and where there are gaps, and I don't want to inadvertently give bad information.


Thank you!

(I do appreciate clarity and precision (at least when it comes to programming))
Praveen Kumar M K
Ranch Hand

Joined: Jul 03, 2011
Posts: 256
Adding to all the information above, from Java 5 onward, using the methods of Thread instance is not the recommended way to go about handling threads. So instead of

use the help of an Executor. Through this, you can delegate the management of the life cycle of a thread to an executor. The executor takes care of start, stop and clean up of the thread(s).
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Praveen Kumar M K wrote:Adding to all the information above, from Java 5 onward, using the methods of Thread instance is not the recommended way to go about handling threads. So instead of

use the help of an Executor.


I don't think there's anything wrong with using Threads directly. This is especially true for beginners. Better to get an idea of how the basic pieces work before moving on to the higher level stuff that hides the details from you. And even for experienced programmers working on serious code, there are times when it's easier just to whip out a Thread, or times when you want the direct control that Executors mask.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Properly Synchronizing a Block of Code
 
Similar Threads
printing threads to a text area
Simple question regarding runnable interface
Printing unicode character
Why this synchronization doesn't work
using thread class to print to a text area