The high concurrency - how to use object-oriented thinking to write concurrent programs?

Foreword

Object-oriented and concurrent programming related? Originally the two are no birds relationship! They belong to two different areas, however, Java puts together the two! And the integration of good results: We use Java object-oriented thinking can make concurrent programming easier! !

How do we use object-oriented thinking to write concurrent programs do? We can be analyzed from the following three perspectives.

  • Package shared variables
  • Identifying constraints between the shared variables
  • Specify Multiplexing Access Policy

Package shared variables

When writing concurrent programs, a core issue we are concerned, in fact, solve the problem of multiple threads simultaneously access shared variables!

Object-oriented thinking there is a very important feature: the package. Simply put, the package is to attribute to the inside of the package and the implementation details of objects, external objects only public methods provided by the target object to indirectly access the internal properties. We shared variable as a property of the object, then, for the shared variable access path is the public method of the object, all entrances to public methods should be set concurrent access policies.

So, we come to a conclusion: the use of object-oriented thinking to write concurrent programs actually quite simple, it is a shared variable as an object attribute package inside, designated concurrent access policy for all public methods!

For example, we will use the counter in many business scenarios, we can define the counter classes as shown below.

public class Counter{
    private long count;
    public synchronized long incrementCount(){
        return ++count;
    }
    public synchronized long getCount(){
        return count;
    }
}

Counter class in the above, there is a shared variable count, two public methods provide both incrementCount () and getCount () sets synchronized genlock, this time, the Counter class is the class of a thread-safe.

In practice, many scenes are more complex than realized counter, for example, our bank accounts, there are card number, name, ID, balances and other shared variables, we do not need to each shared variable must be concerned with concurrency. At this point, we need to carefully analyze these shared variables, see these shared variables which variables are constant. For our bank account, the card number, name, identity card three shared variable is constant. For these same shared variable, we can use the final keyword to modify them, to avoid concurrency issues.

Finally, it should be noted that, when shared variable package, pay attention to "escape the object," the problem! For example, the following program code will be assigned to this constructor global variable global.obj, object initialization has not been completed at this time, when object initialization is not yet complete, object initialization has not been completed at this time, the important thing to say three times! ! Thread read by global.obj x value may be zero. At this time, the object on this "escape" the.

final x = 0;
public FinalFieldExample() { // bad!
  x = 3;
  y = 4;
  // bad construction - allowing this to escape
  global.obj = this;
}

From the example above: http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#finalWrong

Identifying constraints between the shared variables

Constraints between the shared variables are important because they determine the concurrent access policy.

For example, in the mall business, there are commodity inventory management for the concept of a reasonable inventory, inventory can not be too high nor too low, this value has an upper limit and a lower limit. For example, the following class simulates this concept of reasonable inventory.

public class Stock{
    //库存的上限
    private final AtomicLong upper = new AtomicLong(0);
    //库存的下限
    private final AtomicLong lower = new AtomicLong(0);
    //设置库存上限
    public void setUpper(long v){
        upper.set(v);
    }
    //设置库存下限
    public void setLower(long v){
        lower.set(v);
    }
    //其他众多的代码省略
}

At first glance, the above procedure is no problem ah! However, it ignores the constraints is that the lower limit is less than the upper limit of inventory in stock. This is also a lot of people tend to ignore the problem.

See here, it is the first reaction in many people setUpper () method and setLower () method, add the parameter checking logic, for example, after the transformation Stock class as follows.

public class Stock{
    //库存的上限
    private final AtomicLong upper = new AtomicLong(0);
    //库存的下限
    private final AtomicLong lower = new AtomicLong(0);
    //设置库存上限
    public void setUpper(long v){
        if(v < lower.get()){
            throw new IllegalArgumentException();
        }
        upper.set(v);
    }
    //设置库存下限
    public void setLower(long v){
        if(v > upper.get()){
             throw new IllegalArgumentException();
        }
        lower.set(v);
    }
    //其他众多的代码省略
}

Such settings correct? The answer is: to ensure that such a completely different set an upper limit less than the lower limit of inventory in stock.

In fact, there exist race conditions (when the if statement appeared in the program, whether the program should first reaction there is a race condition), explain in detail about the race conditions can be found in " high concurrency - A concurrent programming must be noted three core issues . "

Assume that the upper limit of the existing stock is 10, the lower limit is 3. A thread calls setUpper upper case (5) the stock is set to 5, the thread B calls setLower (7) to set the lower limit inventory 8, if the thread A and thread B are simultaneously executed, the thread A can check the parameters, because At this lower limit inventory thread B has not been set up, this time the stock lower limit or 3,5> 3 is established, so the upper limit of the thread a stock will be set to 5. Similarly, it is possible to thread B, because the upper limit of the stock has not been set up by the thread A check parameter, or the upper limit of this time inventory 10,8 <10 established, thread B will be the lower limit is set to 8 stock. The end result is: up to 5 stocks, the lower limit is 8. The upper limit of the stock is less than the lower limit, the upper limit is not met less than the lower limit constraints.

So, when we recognize the constraints between the shared variable, we must pay attention to the problem of race conditions!

Develop concurrent access strategy

Concurrent access policies to develop more complex, it requires a combination of specific business scenarios to choose. But from the program, we can be summarized as follows scheme.

Avoid sharing

You can use thread local storage and distribution of separate threads for each task to avoid sharing.

The same pattern

The use of this relatively small in Java, more used in other areas, e.g. Actor model, the CSP model and functional programming.

The tube and other synchronization tools

Concurrent Programming in Java for universal solution is the tube (about what is behind the tube article will explain), but for many specific concurrency scenarios, the use of contract and Java synchronization tools provide read-write locks, concurrent containers, etc. Better.

When we write concurrent programs, it must follow certain principles that can be summarized as follows.

Priority use sophisticated tools

For concurrent programming, we use the best priority of concurrent Java utility class provided, because these tools basically concurrent able to meet most business scenarios concurrently.

Try not to use low-level synchronization primitives

Low-level synchronization primitives refers synchronized, Lock Semaphore and so on, these are simple to use, but in reality is not so simple, use the time to be careful. Not a last resort, try not to use them.

Avoid premature optimization

Safety first, concurrent programming is the first to guarantee thread safety, after the re-optimization performance bottlenecks, not too early and over-optimization.

Released 1343 original articles · won praise 2093 · Views 5.25 million +

Guess you like

Origin blog.csdn.net/l1028386804/article/details/104895478