0

I have following code:

public class MyLogger {
   private StringBuilder logger = new StringBuilder();

   public void log(String message, String user) {
      logger.append(message);
      logger.append(user);
   }
}

The programmer must guarantee that a single MyLogger object works properly for a multi-threaded system. How must this code be changed to be thread-safe?

A. synchronize the log method

B. replace StringBuilder with StringBuffer

Please advise the best approach.

2
  • So this accumulates in logger, what is the point? Commented Aug 18, 2017 at 18:41
  • I would probably not use either, preferring a 'LogEntry' class instance that holds a copy of both strings and a command to a logger thread that waits at the end of a Blocking Queue. Commented Aug 18, 2017 at 19:18

2 Answers 2

3

StringBuffer is not enough to guarantee that the two information are always sent grouped :

  logger.append(message);
  logger.append(user);

It guarantees only that append() will not be invoked in a concurrent way and that so you don't risk to break the state of the StringBuffer object.
You could indeed have two threads that interleave during the log() invocation and get these invocations :

Thread 1 : logger.append(message);

Thread 2 : logger.append(message);

Thread 1 : logger.append(user);

Thread 2 : logger.append(user);

This is so better :

  public synchronized void log(String message, String user) {
      logger.append(message);
      logger.append(user);
   }

You can also do the synchronization on the private logger object.
Which has the advantage to not allow the client of the class to lock it outside the class.

Sign up to request clarification or add additional context in comments.

6 Comments

You may want to mention that synchronizing on a private object is a better choice than using synchronized on the method signature.
@Alvin Thompson nice advise. I added it.
Thanks @davidxxx for the nice description. Please let me know if my understandng is wrong: say,Thread 1 got the chance to perform logger.append(message); so T1 has the lock on SB object and on completion of the method execution it will release lock on SB? so T2 can perform logger.append(message); and thus problem may arise? is this what you wanted to describe?
you are welcome. You are close, "and on completion of the method execution it may release lock on".
okay. Hence problem arises when T1 releases the lock and T2 may start performing, i.e., Thread 1 : logger.append(message); Thread 2 : logger.append(message); Thread 1 : logger.append(user); Thread 2 : logger.append(user); otherwise if T1 holds the lock then it can continue with: logger.append(user); and T2 will not get a chance, so this will be like: Thread 1 : logger.append(message); Thread 1 : logger.append(user); Thread 2 : logger.append(message); Thread 2 : logger.append(user);
|
0

Use A, because if you choose to use StringBuffer you could mess the log: This could happen with StringBuffer (will generate wrong log):

logger.append(message); < Thread A
logger.append(message); < Thread B
logger.append(user);  < Thread A
logger.append(user); < Thread B

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.