Java Concurrency (03): multi-threaded concurrent access, synchronization control

This article Source: GitHub · Click here || GitEE · Click here

First, the concurrency issues

Multi-threaded learning, the first to face a complex problem is that access concurrent mode variable, if ignored clear internal processes and reason, often there will be such a problem: after threading variable value is not what you want may also look ignorant to say: this is illogical right?

1, member variables access

Multiple threads to access class member variables, it may lead to various problems.

public class AccessVar01 {
    public static void main(String[] args) {
        Var01Test var01Test = new Var01Test() ;
        VarThread01A varThread01A = new VarThread01A(var01Test) ;
        varThread01A.start();
        VarThread01B varThread01B = new VarThread01B(var01Test) ;
        varThread01B.start();
    }
}
class VarThread01A extends Thread {
    Var01Test var01Test = new Var01Test() ;
    public VarThread01A (Var01Test var01Test){
        this.var01Test = var01Test ;
    }
    @Override
    public void run() {
        var01Test.addNum(50);
    }
}
class VarThread01B extends Thread {
    Var01Test var01Test = new Var01Test() ;
    public VarThread01B (Var01Test var01Test){
        this.var01Test = var01Test ;
    }
    @Override
    public void run() {
        var01Test.addNum(10);
    }
}
class Var01Test {
    private Integer num = 0 ;
    public void addNum (Integer var){
        try {
            if (var == 50){
                num = num + 50 ;
                Thread.sleep(3000);
            } else {
                num = num + var ;
            }
            System.out.println("var="+var+";num="+num);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

Cases where the flow is a member variable concurrent operation, the program is intended to: var = 50, to obtain num = 50, the actual output results are:

var=10;num=60
var=50;num=60

VarThread01A thread processing goes to sleep, num has been conducted threads VarThread01B the sleep time plus 10 operation, which is the result of multi-threaded concurrent access due.

2. The method of private variables

Logic to modify the above code, placed in the num variable method, as a method of a private variable.

class Var01Test {
    // private Integer num = 0 ;
    public void addNum (Integer var){
        Integer num = 0 ;
        try {
            if (var == 50){
                num = num + 50 ;
                Thread.sleep(3000);
            } else {
                num = num + var ;
            }
            System.out.println("var="+var+";num="+num);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

Internal method variables are private, and one current and thread execution method, there will be no interference between threads.

Second, the synchronization control

1, Synchronized keyword

Use: modification methods, or in the form of control of sync blocks, ensuring multiple threads concurrently, only one thread at a time into the process, or the synchronization code block, so that the thread-safe access and process variables. If the modification is a static method, the role of all objects of this class.

Exclusive lock belongs to a class of pessimistic locking, synchronized is a kind of exclusive lock, assuming that in the worst case, there is only one thread of execution, blocking other threads, if high concurrency, time-consuming process, will lead to multiple threads to hang, waiting to hold lock thread releases the lock.

2, modification methods

In this case and the first case the principle is the same, but here in place although modified value added synchronization control, but they dug a pit, there is no limit at the time of reading, a phenomenon commonly known as dirty read.

public class AccessVar02 {
    public static void main(String[] args) {
        Var02Test var02Test = new Var02Test ();
        VarThread02A varThread02A = new VarThread02A(var02Test) ;
        varThread02A.start();
        VarThread02B varThread02B = new VarThread02B(var02Test) ;
        varThread02B.start();
        var02Test.readValue();
    }
}
class VarThread02A extends Thread {
    Var02Test var02Test = new Var02Test ();
    public VarThread02A (Var02Test var02Test){
        this.var02Test = var02Test ;
    }
    @Override
    public void run() {
        var02Test.change("my","name");
    }
}
class VarThread02B extends Thread {
    Var02Test var02Test = new Var02Test ();
    public VarThread02B (Var02Test var02Test){
        this.var02Test = var02Test ;
    }
    @Override
    public void run() {
        var02Test.change("you","age");
    }
}
class Var02Test {
    public String key = "cicada" ;
    public String value = "smile" ;
    public synchronized void change (String key,String value){
        try {
            this.key = key ;
            Thread.sleep(2000);
            this.value = value ;
            System.out.println("key="+key+";value="+value);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void readValue (){
        System.out.println("读取:key="+key+";value="+value);
    }
}

In the thread, the logic has been modified, but not to perform, but the value read in the main thread is meaningless, but also need to join the thread synchronization control on the Read method.

3, the synchronization control logic

Object implementation is based on the synchronization control monitor.

  • Thread access to the Object, Object First get a monitor;
  • If the acquisition is successful, the target will be exclusive;
  • Other threads will fall into sync queue, the thread state becomes blocked;
  • Object holders and other thread releases the lock, the thread will awaken waiting in the queue, try restarting acquire object monitors;

4, the modified code blocks

Point out, the logical code block contains all of the methods, the particle size and modification of the locking procedure is the same, write it in the method. Sync block is a core purpose, size reduction locked resources, just as the table lock and row-level locks.

public class AccessVar03 {
    public static void main(String[] args) {
        Var03Test var03Test1 = new Var03Test() ;
        Thread thread1 = new Thread(var03Test1) ;
        thread1.start();
        Thread thread2 = new Thread(var03Test1) ;
        thread2.start();
        Thread thread3 = new Thread(var03Test1) ;
        thread3.start();
    }
}
class Var03Test implements Runnable {
    private Integer count = 0 ;
    public void countAdd() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized(this) {
            count++ ;
            System.out.println("count="+count);
        }
    }
    @Override
    public void run() {
        countAdd() ;
    }
}

Here is the code for the lock count processing core logic of the action, does not allow concurrent processing.

5, modified static method

Methods Static methods belong to the class hierarchy, the object is not directly call. But the synchronized modification of the static method lock is that all objects of this class.

public class AccessVar04 {
    public static void main(String[] args) {
        Var04Test var04Test1 = new Var04Test() ;
        Thread thread1 = new Thread(var04Test1) ;
        thread1.start();
        Var04Test var04Test2 = new Var04Test() ;
        Thread thread2 = new Thread(var04Test2) ;
        thread2.start();
    }
}
class Var04Test implements Runnable {
    private static Integer count ;
    public Var04Test (){
        count = 0 ;
    }
    public synchronized static void countAdd() {
        System.out.println(Thread.currentThread().getName()+";count="+(count++));
    }
    @Override
    public void run() {
        countAdd() ;
    }
}

If not using the synchronization control, and logically sensory outputs the result should be as follows:

Thread-0;count=0
Thread-1;count=0

After addition of the synchronization control, the actual test output:

Thread-0;count=0
Thread-1;count=1

6 Notes

  • Inheritance neutron parent class overrides the method, the synchronized transfer key not inherit characteristics, must be explicitly declared;
  • Synchronized keyword can not be used on construction method, the constructor sync block support;
  • Interface method, abstract method does not support the synchronized keyword;

Three, Volatile keyword

1, the basic description

Java memory model, in order to improve performance, the thread Copies of variables to be visited in their working memory. So there will be the same variable at a time, the value in a threaded environment may be related to the value of another thread environment, appear inconsistent.

Use volatile modifications member variables, methods can not be modified, that identifies the threads need to get from the shared memory when accessing this variable, the variable is modified, but also need to synchronize flushed to shared memory to ensure the visibility of the variables of all threads .

2, Use Cases

class Var05Test {
    private volatile boolean myFlag = true ;
    public void setFlag (boolean myFlag){
        this.myFlag = myFlag ;
    }
    public void method() {
        while (myFlag){
            try {
                System.out.println(Thread.currentThread().getName()+myFlag);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

3 Notes

  • Visibility only to ensure that each read the latest value, but does not support atomic variable operations;
  • volatile and does not block the thread method, but will block synchronization control;
  • Java synchronization control fundamental: to ensure atomicity and visibility with inferior resources;

Fourth, the source address

GitHub·地址
https://github.com/cicadasmile/java-base-parent
GitEE·地址
https://gitee.com/cicadasmile/java-base-parent

Java Concurrency (03): multi-threaded concurrent access, synchronization control

Guess you like

Origin blog.51cto.com/14439672/2482929