Reputation: 601
I have a class TestLogger
that has a void method log(String s)
, which may be accessed by multiple threads. Here is my code
public class TestLogger {
private static final StringBuffer buffer = new StringBuffer();
public static void log(String s) {
buffer.append(s);
}
}
I am not sure here if I used the thread safe class StringBuffer
, do I still need to put synchronized keyword on the method log(String)
to ensure thread safety of the method? And how about this method
public static void log(String s, int type) {
if (type == 0)
buffer.append(s);
if (type == 1)
buffer.append("SOME HEADER " + s);
}
here type is not modified in the method log. Do I need to use synchronized keyword?
In Java, there are both synchronized keyword and thread safe classes that can provide thread safety. I am not sure when to use one and the other?
Upvotes: 1
Views: 1991
Reputation: 27115
And how about this method...
Your two methods are equally thread-safe (or not!, see below the line). No matter which method is called, the same thing will happen: Exactly one string will be added to the shared buffer.
Using thread-safe objects does not make a program thread-safe. It's up to you to decide what "thread-safe" means.
When somebody tells you that some class is thread-safe, what they're promising is, that there's no way that multiple threads calling the class's methods can make any of them behave in "wrong" ways.
And what does "wrong" mean? Well, it depends. Certainly, any behavior that disagrees with the class's documentation would be wrong. And often, any behavior that disagrees with what a reasonable programmer would expect could be called wrong too.
In the case of StringBuffer, here's what "thread-safe" means: It means, that:
Your example method calls are thread safe simply by virtue of the fact that each one makes just one call on a thread-safe shared object.
If your example had several shared objects though, that's when the individual thread-safety of the objects might not add up to thread-safety for the whole algorithm.
Upvotes: 3
Reputation: 1905
StringBuilder
is not thread safe in java. So you can use StringBuffer
which is thread safe.
The synchronized
keyword can be used in two different ways.
Synchronized Methods: It makes the method thread-safe.
public synchronized static void log (String log) {
buffer.append(log);
}
Synchronized Statements: It make the specifed object thread-safe.
public static void log(String log) {
synchronized (buffer) {
buffer.append(log);
}
}
Upvotes: -1
Reputation: 311393
Since either implementation of this method accesses buffer
at most once, you don't technically need to synchronize the method, but it's a really bad practice.
First, it's extremely fragile. It's enough that some careless developer takes a look at this method and decides to "optimize" it (to better Java code!) for you to lose the StringBuffer
's synchronization:
public static void log(String s, int type) {
if (type == 0)
buffer.append(s);
if (type == 1)
buffer.append("SOME HEADER ").optimize(s);
}
This snippet shows two separate calls to append
, so if you concurrently call log('A', 1)
and log('B',1)
, your resulting buffer may very well be "SOME HEADER SOME HEADER AB"
.
Second, even if you don't technically break synchronization, by relying solely on the StringBuffer
to supply your synchronization needs, you may discover slight behavior oddities. For example, consider a future request to also log the message's time:
public static void log(String s) {
Date d = new Date();
buffer.append(d.toString() + " " + s);
}
If you have a considerable number of concurrent calls to this method, you may experience thread A creating the new Date
instance, context switching to another thread that completes the entire method and then returning to thread A. This will make your log appear as though it's moving back in time, which is definitely not what you want.
And third, and most importantly, defining the method as synchronized
has a declarative value. It conveys the information of how this method behaves in a multithreaded context and how you'd expect two concurrent call to react to each other. In a public utility function designed to be used by others, this is paramount.
Upvotes: 2
Reputation: 62583
Since StringBuffer is thread safe, you do not need to have another synchronization point around it (this is what synchronized would do).
Upvotes: 0