-1

i am unable to get synchronized blocks in java

i read this following post but didn't quite get about syn-blocks and locks

Synchronized block not working

i don't know why below code is not outputting uniform array of A's,B's,C's even after i synchronized it..

    public class synchronizeblock
{
    static StringBuffer s=new StringBuffer();
    public static void main(String []args)
    {
        Threading t1=new Threading(s,'a');
        Threading t2=new Threading(s,'b');
        Threading t3=new Threading(s,'c');
        t1.start();
        t2.start();
        t3.start();     
    }
}
class Threading extends Thread
{
    StringBuffer sb; 
    char ch;

    Threading()
    {

    }
    Threading(StringBuffer sb,char ch)
    {
        this.sb=sb;
        this.ch=ch;
    }
    public void run()
    {
        synchronized(this)   // this(current instance) acts as lock ??
        {
                for(int i=0;i<20;++i)
                {
                    System.out.print(ch);
                }
        }       
    }

}

one of cases of output is as below:

bbbbbbbbbbbbbaccccccccccccccccccccaaaaaaaaaaaaaaaaaaabbbbbbb

my concern is that once a thread is started ,say thread with character 'b' (be it thread-"one")shouldn't it be completed before another thread gets chance to run because thread "one" got lock on the object,correct me if am wrong and i have following questions

  1. it's really confusing "what gets locked" and "what acts as lock". So explain what exactly got locked in my code

  2. and what should i do to get uniform output (by saying uniform output here ,i mean that once a thread starts its character should get printed 20 times)

Community
  • 1
  • 1
manifold
  • 437
  • 6
  • 23
  • 1
    `synchronized` takes a lock on the given object, `this` is this case. You have 3 different `Threading` instances, so they lock 3 different objects, and since nothing else tries to lock those objects, the locks have no effect. – Andreas Jun 11 '16 at 09:10
  • When you say "got lock on the object", what object do you mean? – David Schwartz Jun 11 '16 at 09:16
  • @Andreas so consider synchronized(aaaa) so aaaa does't act as lock, rather it gets locked,correct me if am wrong.... – manifold Jun 11 '16 at 09:17
  • @DavidSchwartz current instance – manifold Jun 11 '16 at 09:21
  • @viru The phrasing used in the [Java Language Specification](https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.19) is: *"The executing thread locks the **monitor associated with** `aaaa`."* – Andreas Jun 11 '16 at 09:35

3 Answers3

2

first of all StringBuffer are

String buffers are safe for use by multiple threads. The methods are synchronized where necessary so that all the operations on any particular instance behave as if they occur in some serial order that is consistent with the order of the method calls made by each of the individual threads involved.

and the rest you can read in bottom of your question but problem about not print my output like this A's B's C's its that your Threads run even if the current thread not finish for that can use join() method its tell's the other thread wait until my job its finish then go do your job so, your main methods look like this

      Threading t1 = new Threading(s,'a');
      Threading t2 = new Threading(s,'b');
      Threading t3 = new Threading(s,'c');
      t1.start();
      t1.join();
      t2.start();
      t2.join();
      t3.start();
Hosseini
  • 547
  • 3
  • 15
0

Use the sb for synchronizing because otherwise you do not synchronize with the other threads (you are locking the object for itself). Or create a locking object which is used for synchronizing between the three different objects.

public class Threading extends Thread
{
    private Object synchronizationContext;
    private StringBuffer sb; 
    private char ch;

    Threading(StringBuffer sb,char ch, Object synchronizationContext)
    {
        this.sb=sb;
        this.ch=ch;
    }
    public void run()
    {
        synchronized(synchronizationContext)
        {
            for(int i=0;i<20;++i)
            {
                System.out.print(ch);
            }
        }       
    }
}

and main use the same synchronizationContext for all.

public static void main(String []args)
{
    Object synchronizationContext = new Object();
    Threading t1 = new Threading(s,'a', synchronizationContext);
    Threading t2 = new Threading(s,'b', synchronizationContext);
    Threading t3 = new Threading(s,'c', synchronizationContext);
    t1.start();
    t2.start();
    t3.start();     
}
wake-0
  • 3,918
  • 5
  • 28
  • 45
0
  1. it's really confusing "what gets locked" and "what acts as lock"

Not sure what you are asking. When we do a synchronized (obj) then the obj is what is being locked. The threads do the locking which may block if another thread already holds the lock. It's not proper to say that the obj "acts as a lock".

synchronized(this)   // this(current instance) acts as lock ??

You are locking on this which is the problem, see below.

2.and what should i do to get uniform output (by saying uniform output here

In your case, the problem is that you a synchronizing on this. Each thread is locking on a different object. If you want them to have a mutex lock to have exclusive access to printing their characters, then you will need to pass in a common object that they all lock on:

final Object lock = new Object();
Threading t1 = new Threading(lock,'a');
Threading t2 = new Threading(lock, b');
Threading t3 = new Threading(lock,'c');
...
class Threading extends Thread {
    final Object lock;
    final char ch;
    public Threading(Object lock, char ch) {
       this.lock = lock;
       this.ch = ch;
    }
    public void run() {
        // lock on a common lock object in all 3 threads
        synchronized (lock) {
            for(int i = 0; i < 20; i++) {
                System.out.print(ch);
            }
        }
    }
}
Gray
  • 115,027
  • 24
  • 293
  • 354