Synchronized block not working

*爱你&永不变心* 提交于 2019-11-29 09:28:09

4. The synchronized block of code will obtain a lock on the StringBuffer object from step 3.

Well, you're not doing that, are you?

synchronized(this) {

You're obtaining a lock on the instance of MySyncBlockTest on which that run() method is being called. That ... isn't going to do anything. There's no contention for that resource; each Thread has its own instance of MySyncBlockTest.

You should lock on the StringBuffer object

 synchronized(sb) {
            for (int i=0; i<10; i++) {
                System.out.print(sb);
            }

I was confused too. The answer provided by Brian is correct

synchronized (this){

is for getting the lock on an instance. It would be useful when there is a single instance of a class and multiple threads accessing it.

I wrote the following program to demonstrate this:

package com.threads.chapter9;

public class TestSunchronizedBlocksUsingRunnable implements Runnable {
StringBuffer s;

@Override
public void run() {
    synchronized (this) {
        for (int i = 1; i <= 100; i++) {
            System.out.println(i);
        }
        char c = s.charAt(0);
        c++;
        s.setCharAt(0, c);
    }
}

TestSunchronizedBlocksUsingRunnable(StringBuffer s) {
    this.s = s;
}

public static void main(String[] args) {
    StringBuffer s = new StringBuffer("A");
    TestSunchronizedBlocksUsingRunnable instance1 = new TestSunchronizedBlocksUsingRunnable(s);
    Thread thread1 = new Thread(instance1);
    Thread thread2 = new Thread(instance1);
    Thread thread3 = new Thread(instance1);
    thread1.start();
    thread2.start();
    thread3.start();
}

}

The above code will display the same output but the scenario is completely different. So what you use inside synchronized block is really crucial.

The output that you want, thats possible with multiple threads of single object, try this method

public class MultiThreading implements Runnable {
public static void main(String [] arg)
{
MultiThreading a=new MultiThreading(20);
Thread t0=new Thread(a);   //
Thread t1=new Thread(a);   // Multiple Threads of single object
Thread t2=new Thread(a);   // 
t0.start();
t1.start();
t2.start();
}
private int count;
MultiThreading(int a)
{this.count=a;
}
public void run()
{
synchronized(this){   
String t_name=new String("");
t_name=Thread.currentThread().getName().toString();
    for(int i=0;i<count;i++)
    if(t_name.equals("Thread-0".toString())) // mean t0
        System.out.print("A");

    else if(t_name.equals("Thread-1".toString())) // mean t1
        System.out.print("B");

    else if(t_name.equals("Thread-2".toString())) // mean t1
        System.out.print("C");
System.out.print("\n");
                  }
} // end of run
}
 EXERCISE 9-2 from SCJP:
Try this For Synchronozing on stringBuffer Object.
It is giving required output.




class letterThread extends Thread
{
StringBuffer putLetter;

letterThread(StringBuffer str)
{
    this.putLetter=str;
}

public void run()
{

    synchronized (putLetter) {

        if(Thread.currentThread().getName().equals("th2"))
        {
            this.putLetter=new StringBuffer("B");
        }
        else if(Thread.currentThread().getName().equals("th3"))
        {
            this.putLetter=new StringBuffer("C");
        }

        for(int i=1;i<11;i++)
        {
            System.out.print(putLetter+"");
        }
        System.out.println();
    }
}   
}

public class Manager
{
public static void main(String args[])
{
    StringBuffer str=new StringBuffer("A");
    letterThread th1=new letterThread(str);
    letterThread th2=new letterThread(str);
    letterThread th3=new letterThread(str);

    th1.setName("th1");
    th2.setName("th2");
    th3.setName("th3");

    th1.start();
    th2.start();
    th3.start();

}
 }
Mahesh

EXERCISE 13-2 from SCJP7

public class ThreadSyncronization extends Thread {

    StringBuffer sBuffer;
    public ThreadSyncronization(StringBuffer s,String name){
        this.sBuffer=s;
        this.setName(name);
    }
    public ThreadSyncronization(){
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        StringBuffer ch = new StringBuffer("A");
        Thread t1 = new ThreadSyncronization(ch,"first");
        Thread t2 = new ThreadSyncronization(ch,"second");
        Thread t3 = new ThreadSyncronization(ch,"third");
        t1.start();
        t2.start();
        t3.start();
    }

    public void run(){
        synchronized (sBuffer) {
            System.out.println(this.getName());
            for(int i=0;i<10;i++) {
                System.out.print(sBuffer+":"+i+" ");
                try{Thread.sleep(500);} catch(InterruptedException e) {System.out.println(e);}
            }           
            System.out.println();
            // increment char
           char c = this.sBuffer.charAt(0);
           this.sBuffer.setCharAt(0, ++c);
        }

    }

}

You could replace

        if (sb.charAt(0)=='A')
            sb.setCharAt(0, 'B');
        else
            sb.setCharAt(0, 'C');

with

sb.setCharAt(0, (char) (sb.charAt(0) + 1));

package com.practice.ThreadPackage;

class ThreadParent extends Thread {

StringBuffer data;

public void run() {
    synchronized (this.data) {

        System.out.println(this.getName());

        for (int i = 0; i < 10; i++) {

            System.out.print(this.data.toString());
        }

        System.out.println();
        this.data.setCharAt(0, ((char) (this.data.charAt(0) + 1)));
    }
}

ThreadParent(StringBuffer obj) {
    this.data = obj;
}

}

public class ThreadClass { public static void main(String args[]) {

    StringBuffer str = new StringBuffer("A");
    ThreadParent obj = new ThreadParent(str);
    ThreadParent obj1 = new ThreadParent(str);
    ThreadParent obj2 = new ThreadParent(str);
    obj.setName("Thread1");
    obj1.setName("Thread2");
    obj2.setName("Thread3");
    obj.start();
    obj1.start();
    obj2.start();

}

}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!