Java multi-threading learning (two) synchronized keyword (2)

(2) synchronized sync block of statements

Disadvantage of a synchronized method

Use the synchronized keyword to declare a method sometimes there is a serious shortcoming, such as we have to get a lock after two threads A thread calls a synchronized method, then B will have to wait another thread A executed, but if the A's execution it is a time-consuming task, then this will be very time consuming.

A first look at examples of the shortcomings exposed synchronized method, then look at how to solve this problem by synchronized sync block.

Task.java

public class Task {

    private String getData1;
    private String getData2;

    public synchronized void doLongTimeTask() {
        try {
            System.out.println("begin task");
            Thread.sleep(3000);
            getData1 = "长时间处理任务后从远程返回的值1 threadName="
                    + Thread.currentThread().getName();
            getData2 = "长时间处理任务后从远程返回的值2 threadName="
                    + Thread.currentThread().getName();
            System.out.println(getData1);
            System.out.println(getData2);
            System.out.println("end task");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

CommonUtils.java

public class CommonUtils {

    public static long beginTime1;
    public static long endTime1;

    public static long beginTime2;
    public static long endTime2;
}

MyThread1.java

public class MyThread1 extends Thread {
    private Task task;
    public MyThread1(Task task) {
        super();
        this.task = task;
    }
    @Override
    public void run() {
        super.run();
        CommonUtils.beginTime1 = System.currentTimeMillis();
        task.doLongTimeTask();
        CommonUtils.endTime1 = System.currentTimeMillis();
    }
}

MyThread2.java

public class MyThread2 extends Thread {
    private Task task;
    public MyThread2(Task task) {
        super();
        this.task = task;
    }
    @Override
    public void run() {
        super.run();
        CommonUtils.beginTime2 = System.currentTimeMillis();
        task.doLongTimeTask();
        CommonUtils.endTime2 = System.currentTimeMillis();
    }
}

Run.java

public class Run {

    public static void main(String[] args) {
        Task task = new Task();

        MyThread1 thread1 = new MyThread1(task);
        thread1.start();

        MyThread2 thread2 = new MyThread2(task);
        thread2.start();

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long beginTime = CommonUtils.beginTime1;
        if (CommonUtils.beginTime2 < CommonUtils.beginTime1) {
            beginTime = CommonUtils.beginTime2;
        }

        long endTime = CommonUtils.endTime1;
        if (CommonUtils.endTime2 > CommonUtils.endTime1) {
            endTime = CommonUtils.endTime2;
        }

        System.out.println("耗时:" + ((endTime - beginTime) / 1000));
    }
}

From the point of view of time running, the problem is obvious synchronized method. You can use synchronized block synchronized to solve this problem. But be careful use synchronized sync blocks, if synchronized synchronized block use bad words will not bring to enhance efficiency.

Using two synchronized (this) block synchronization code

Examples of modifications Task.java follows:

public class Task {

    private String getData1;
    private String getData2;

    public void doLongTimeTask() {
        try {
            System.out.println("begin task");
            Thread.sleep(3000);

            String privateGetData1 = "长时间处理任务后从远程返回的值1 threadName="
                    + Thread.currentThread().getName();
            String privateGetData2 = "长时间处理任务后从远程返回的值2 threadName="
                    + Thread.currentThread().getName();

            synchronized (this) {
                getData1 = privateGetData1;
                getData2 = privateGetData2;
            }

            System.out.println(getData1);
            System.out.println(getData2);
            System.out.println("end task");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

From the above code can be seen when a thread to access a synchronized object synchronization code block, then another thread can access any of the objects that are not synchronized sync block.

Although the time shortened, but we consider the synchronized block of code really is synchronous it? It really holds the lock object's current call it?

Yes. Not synchronized code block on asynchronous execution, synchronization is performed in the synchronized code block.

Three synchronized (object) code blocks using inter

MyObject.java

public class MyObject {
}

Service.java

public class Service {

    public void testMethod1(MyObject object) {
        synchronized (object) {
            try {
                System.out.println("testMethod1 ____getLock time="
                        + System.currentTimeMillis() + " run ThreadName="
                        + Thread.currentThread().getName());
                Thread.sleep(2000);
                System.out.println("testMethod1 releaseLock time="
                        + System.currentTimeMillis() + " run ThreadName="
                        + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

ThreadA.java

public class ThreadA extends Thread {

    private Service service;
    private MyObject object;

    public ThreadA(Service service, MyObject object) {
        super();
        this.service = service;
        this.object = object;
    }

    @Override
    public void run() {
        super.run();
        service.testMethod1(object);
    }
}

ThreadB.java

public class ThreadB extends Thread {
    private Service service;
    private MyObject object;

    public ThreadB(Service service, MyObject object) {
        super();
        this.service = service;
        this.object = object;
    }

    @Override
    public void run() {
        super.run();
        service.testMethod1(object);
    }

}

Run1_1.java

public class Run1_1 {

    public static void main(String[] args) {
        Service service = new Service();
        MyObject object = new MyObject();

        ThreadA a = new ThreadA(service, object);
        a.setName("a");
        a.start();

        ThreadB b = new ThreadB(service, object);
        b.setName("b");
        b.start();
    }
}

Two threads use the same "object monitor", so operating results are synchronized.

So, what is the effect if a different object monitor will happen?
Modify Run1_1.java as follows:

public class Run1_2 {

    public static void main(String[] args) {
        Service service = new Service();
        MyObject object1 = new MyObject();
        MyObject object2 = new MyObject();

        ThreadA a = new ThreadA(service, object1);
        a.setName("a");
        a.start();

        ThreadB b = new ThreadB(service, object2);
        b.setName("b");
        b.start();
    }
}

Two threads using a different "object monitor", so the results are not synchronized with the run.

The synchronization of the synchronized code block of four

When object access a synchronized (this) block, code block other threads from accessing the code block will be blocked on the same object in all other synchronized (this), indicating that synchronized (this) "object monitor" block used Is a.
That is the same and synchronized methods, synchronized (this) is a locking block of the current object.

Also by the above study, we can draw two conclusions.

  1. Other objects synchronized execution thread synchronization method (the one we introduced, may need to review a fancy article) presents synchronization effect and synchronized (this) block;
  2. If two threads use the same "Object Monitor", the results synchronization, or sync.

Five static synchronized synchronized synchronized manner (class) block

static synchronized keyword added and synchronized static methods (class) is the code block is locked to the Class class, whereas non-static synchronized keyword static method applied to the object is locked.

Service.java

package ceshi;

public class Service {

    public static void printA() {
        synchronized (Service.class) {
            try {
                System.out.println(
                        "线程名称为:" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "进入printA");
                Thread.sleep(3000);
                System.out.println(
                        "线程名称为:" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "离开printA");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    synchronized public static void printB() {
        System.out.println("线程名称为:" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "进入printB");
        System.out.println("线程名称为:" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "离开printB");
    }

    synchronized public void printC() {
        System.out.println("线程名称为:" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "进入printC");
        System.out.println("线程名称为:" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "离开printC");
    }

}

ThreadA.java

public class ThreadA extends Thread {
    private Service service;
    public ThreadA(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.printA();
    }
}

ThreadB.java

public class ThreadB extends Thread {
    private Service service;
    public ThreadB(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.printB();
    }
}

ThreadC.java

public class ThreadC extends Thread {
    private Service service;
    public ThreadC(Service service) {
        super();
        this.service = service;
    }
    @Override
    public void run() {
        service.printC();
    }
}

Run.java

public class Run {
    public static void main(String[] args) {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();

        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();

        ThreadC c = new ThreadC(service);
        c.setName("C");
        c.start();
    }
}

As can be seen from the results: The method as synchronized with the synchronized synchronous static (class) block locks held, are Class locks, lock on the Class Object instances of all functions. synchronized keyword is added to the non-static method static object lock is held.

Thread A, B and C thread holding a lock is not the same, so the A and B synchronization run, but to run and C are not synchronized.

Six data type String constant pool property

String constant pool has a cache function in Jvm

    String s1 = "a";
    String s2="a";
    System.out.println(s1==s2);//true

The above code output is true. Why is this?

String String constant pool there is only one! That is, after performing the first complete line of code, existing constant pool "a", then s2 does not apply for a new space in the constant pool, but directly to an existing string memory address to the s2.

Because of the constant pool attribute data type String, so synchronized (string) will be some problems in some cases, when used, for example, two threads to run
the synchronized ( "abc") {
} and
the synchronized ( "abc") {
} modified when the method, these two threads will hold the same lock, resulting in only one thread at a time can run. So try not to use synchronized (string) using synchronized (object)

Reprinted: https://blog.csdn.net/qq_34337272/article/details/79670775

Guess you like

Origin blog.csdn.net/weixin_39940206/article/details/93493993