unlocked

As far as personality is concerned, we can be divided into optimists and pessimists. Optimists always look on the bright side of things. They think that everything is always less likely to go wrong, the probability of error is small, so we can do things with impunity. If really unfortunate encountered a problem, it is to change without then add mian. For the pessimistic people, they are always afraid of making mistakes, that is the norm, so no matter how big or small, they have to consider everything, to make sure that nothing is wrong.

Locking is a pessimistic strategy for concurrency control. It always assumes that every critical section operation will cause a conflict, so you must be careful with each operation. If more than one thread needs access to a critical section at the same time, it is better to sacrifice performance by keeping the thread waiting, so locking blocks thread execution. Lockless is an optimistic strategy that assumes there will be no conflicts in access to resources. Since there are no conflicts, there is no need to wait, so all threads can execute without pausing. The lockless policy uses CAS comparison switching techniques to identify thread conflicts and, once a conflict is detected, retries the current operation until there are no conflicts.

A Different concurrency Strategy: Comparative Exchange (CAS)

Procedure of CAS algorithm: it contains three parameters CAS(V,E,N). V is the variable to be updated, E is the expected value, and N is the new value. The value of V is set to N only if the value of V is equal to the value of E. If the value of V is different from the value of E, then another thread has already made the update, and the current thread does nothing.

Atomic

Java Java. Util. Concurrent packages in addition to providing the underlying lock, concurrent collections, it also provides a set of atomic operation wrapper class, which is located in Java. Util. Concurrent. The atomic package.

AtomicInteger, for example, provides the following operations:

  • Add value and return new value:int addAndGet(int delta)
  • Add 1 to return the new value:int incrementAndGet()
  • Get the current value:int get()
  • Set in CAS mode:int compareAndSet(int expect, int update)

Atomic classes are thread-safe access implemented in a lock-free manner. Its main principle is to use CAS: Compare and Set.

public final int incrementAndGet(a) {
    return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
Copy the code
public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

    return var5;
}
Copy the code

IncrementAndGet, for example, actually calls the getAndAddInt method on the unsafe instance. The Unsafer class provides some of the underlying operations, and the atomic operations in the atomic package are mainly compareAndSwapInt provided through the unsafe class. CompareAndSwapLong and a series of methods to provide CAS operations to implement.

Example: i++

public class AtomicityDemo {
    private static AtomicInteger atomicInteger = new AtomicInteger(0);
    public static void main(String[] args) throws InterruptedException {

        List<Thread> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Thread t = new Thread(() -> {
                for (int j = 0; j < 100000; j++) { atomicInteger.incrementAndGet(); }}); t.start(); list.add(t); }for(Thread t : list) { t.join(); } System.out.println(atomicInteger.get()); }}Copy the code

conclusion

Using Java. Util. Concurrent. Atomic atomic operation can simplify multithreaded programming:

  • Atomic operations achieve lockless thread safety;
  • Suitable for counters, accumulators, etc.