Java multi-threading learning (three) - synchronized (on)

In the first two sections of "Java multi-threading learning (a) - Multithreading Basics" and "Java multi-threading learning (two) - Thread class method of introduction" We contacted the concept of a thread-safe and non-thread-safe, which section have to learn about the use of synchronized keyword.

1, thread safety variables

"Non-thread-safe" issues exist in the "instance variables", if the method is inside a private variable, "non-thread-safe," the problem does not exist. If two threads simultaneously operating object instance variables, there will be a non-thread-safe problem, the solution is to add a control to add synchronized keyword synchronized on method.

2, a plurality of lock multiple objects

Look at the code:

public class HasSelfPrivateNum {
    // 创建被同步关键字修饰的方法
    private int num = 0;
    synchronized public void add(String name){

        try {
            if ("a".equals(name)){
                num = 100;
                System.out.println("a set over");
                Thread.sleep(2000);
            }else {
                num = 200;
                System.out.println("b set over");
            }
            System.out.println(name + " num = " + num);
        }catch (InterruptedException e){
            e.printStackTrace();
        }

    }
}
public class ThreadA extends Thread {
// 创建线程,构造器传参为上面方法的对象
    private HasSelfPrivateNum hasSelfPrivateNum;

    public ThreadA(String name, HasSelfPrivateNum hasSelfPrivateNum){
        super();
        this.hasSelfPrivateNum = hasSelfPrivateNum;
        this.setName(name);
    }

    @Override
    public void run() {
        super.run();
        hasSelfPrivateNum.add(this.getName());
    }
}
// main方法和输出
 public static void main(String[] args){
        HasSelfPrivateNum hasSelfPrivateNum = new HasSelfPrivateNum();
        HasSelfPrivateNum hasSelfPrivateNum1 = new HasSelfPrivateNum();
        ThreadA threadA = new ThreadA("a", hasSelfPrivateNum);
        ThreadA threadA1 = new ThreadA("b", hasSelfPrivateNum1);
        threadA.start();
        threadA1.start();
    }

b set over
a set over
b num = 200
a num = 100

As this example creates two HasSelfPrivateNum object, so it will have two locks, so the results are running asynchronously.

Lock are synchronized to obtain the object lock, rather than as a lock piece of code or method. So in the example above, the first implementation of which thread lock Lock method with the synchronized keyword, then the thread which holds the method belongs to the object, then other threads can only wait in a state if multiple threads access the same an object. However, if multiple threads access multiple objects, JVM creates multiple locks.

The main direction changed a bit:

public static void main(String[] args){
        HasSelfPrivateNum hasSelfPrivateNum = new HasSelfPrivateNum();
        //HasSelfPrivateNum hasSelfPrivateNum1 = new HasSelfPrivateNum();
        ThreadA threadA = new ThreadA("a", hasSelfPrivateNum);
        ThreadA threadA1 = new ThreadA("b", hasSelfPrivateNum);
        threadA.start();
        threadA1.start();
    }
----
a set over
a num = 100
b set over
b num = 200

And can be seen threadA threadA1 get the lock of an object, it is the order of the output.

3, synchronized with the method of the object

Through the above we know that the object lock synchronized locks are acquired, rather than as a piece of code or lock method. If multiple threads access the same object, which thread to perform the method with the synchronized keyword, then the thread which holds this method, other threads can only be in a wait state. If multiple threads access the object is not necessarily more, because more than one object will have multiple locks.

If multiple threads access the synchronized keyword is not the same object in the modified method, the thread asynchronous call unmodified method.

4, dirty read

When the assignment is carried out simultaneously, but there may be some unexpected surprises when the value of this case is that dirty read. Case of dirty read occurs in reading the instance variable, this value has been modified by another thread.

public class DirtyReadTest {
    // 创建同步修改数据方法,非同步取数据方法
    public String username = "A";
    public String password = "AA";
    synchronized public void setValue(String username, String password){
        try {
            this.username = username;
            Thread.sleep(5000);
            this.password = password;
            System.out.println("setValue method: username = " + username + " password = " + password);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }

    public void getValue(){
        System.out.println("getValue method: username = " + username + " password = " + password);
    }

}
public class ThreadTest extends Thread {
    private DirtyReadTest dirtyReadTest;
    public ThreadTest(DirtyReadTest dirtyReadTest){
        super();
        this.dirtyReadTest=dirtyReadTest;
    }

    @Override
    public void run() {
        super.run();
        dirtyReadTest.setValue("B", "BB");
    }
}

Output:

public static void main(String[] args) throws Exception{
        DirtyReadTest dirtyReadTest = new DirtyReadTest();
        ThreadTest threadTest = new ThreadTest(dirtyReadTest);
        threadTest.start();
        Thread.sleep(200);
        dirtyReadTest.getValue();
    }
getValue method: username = B password = AA
setValue method: username = B password = BB

The solution is to add synchronized keyword on the getValue method.

When the synchronized method Thread 1 calls when an object A, thread 1 will acquire the lock of the object, which is the thread 2 is unable to obtain any of the object's methods are synchronized modified, but not synchronized modification methods can be accessed.

5, synchronized lock reentrant

In use the synchronized, when a thread is obtained a lock of the object, is not released, the lock of the object requested again can be acquired again. synchronized modification of the method of an object can access the object being synchronized modified in other ways, if not reentrant locks can cause deadlocks.

Test Methods:

public class Service {
    synchronized public void service1(){
        System.out.println("service1");
        service2();
    }

    synchronized public void service2(){
        System.out.println("service2");
        service3();
    }

    synchronized public void service3(){
        System.out.println("service3");

    }
}
public class ThreadTest extends Thread {
    @Override
    public void run() {
        super.run();
        Service service = new Service();
        service.service1();
    }
}
public static void main(String[] args){
        ThreadTest threadTest = new ThreadTest();
        threadTest.start();
    }

service1
service2
service3

Reentrant lock is also supported in the parent-child class inherits the environment, the subclass can synchronize the parent class called through reentrant lock. This is no longer writing code, you can write a self-written.

6, abnormal, the automatic release

When a thread exception code execution occurs, all its locks are automatically released.

7, synchronization does not have inheritance

If the parent class has a method with the synchronized keyword, subclass inherits and override this method. However, synchronization can not be inherited, they still need to add synchronized keyword in the subclass methods.

This section of the code GitHub .


Welcome to public concern number:
No micro-channel public

Guess you like

Origin blog.csdn.net/qq_36447151/article/details/93708687