Art Notes of Java Concurrent Programming (1) challenges of concurrent programming

Time:2021-10-17

This paper is organized by colodoo (paper umbrella)

QQ 425343603

Java learning exchange group (717726984)

Reference book the art of Java Concurrent Programming

The original text will be attached to the notes. If you don’t want to see the original text, you can only look at the summary of the list

Context switching

  • Single core processor supports multithreading
  • The CPU supports multithreading by allocating CPU time slices to each thread
  • Time slice is the time allocated by the CPU to each thread
  • The time slice has a short time and keeps switching, which makes people feel that multiple threads are executed at the same time
  • The time slice is generally tens of milliseconds (MS)
  • The CPU circularly executes tasks through the time slice allocation algorithm. When the task points to a time slice, it will go to the next task
  • Before switching, the state of the previous task will be saved so that the task state can be loaded next time
  • The process from saving to reloading a taskJust onceContext switching

It’s like reading two trees at the same time. When we read another English technical book, we find that we don’t know a word, so we open the Chinese and English fields, but before we put down the English technical book, the brain must first remember how many pages and lines the book has read, and then we can continue to read the book after checking the words. Such switching will affect the reading efficiency. Similarly, context switching will also affect the execution speed of the thread.

  • Context switching will affect the execution speed of threads

Must multithreading be fast

public class ConcurrencyTest {
    
    private static final long count = 1000000001;
    public static void main(String[] args) throws InterruptedException {
        concurrency();
        serial();
    }
    
    private static void concurrency() throws InterruptedException {
        long start = System.currentTimeMillis();
        Thread thread = new Thread(new Runnable() {
            public void run() {
                int a = 0;
                for(long i = 0; i < count; i++) {
                    a += 5;
                }
            }
        });
        thread.start();
        int b = 0;
        for(long i = 0; i < count; i++) {
            b--;
        }
        long time = System.currentTimeMillis() - start;
        thread.join();
        System.out.println("concurrency: " + time + "ms, b=" + b);
    }
    
    private static void serial() {
        
        long start = System.currentTimeMillis();
        int a = 0;
        for(long i = 0; i < count; i++) {
            a += 5;
        }
        int b = 0;
        for(long i = 0; i < count; i++) {
            b--;
        }
        long time = System.currentTimeMillis() - start;
        System.out.println("serial: " + time + "ms, b=" + b + ", a=" + a);
        
    }
    
}

Art Notes of Java Concurrent Programming (1) challenges of concurrent programming

  • Threads have the overhead of creating and switching contexts

Test context switching times and duration

Art Notes of Java Concurrent Programming (1) challenges of concurrent programming

How to reduce context switching

  • Lock free concurrent programming
  • CAS algorithm
  • Use minimal threads
  • Synergetic process

Lockless concurrent thread

When multithreading competes for locks, it will cause context switching. Therefore, when multithreading processes data, some methods can be used to avoid using locks, such as segmenting the data ID according to the hash algorithm, and different threads process different data.

CAS algorithm

Java’s atomic package uses CAS algorithm to update data without locking.

Use minimal threads

It is easy to create unnecessary threads. For example, there are few tasks, but many threads are created to process them, which will cause a large number of threads to be in a waiting state.

Synergetic process

Realize multi task scheduling in a single thread, and maintain the switching between multiple tasks in a single thread.

Reduce context switching practice

  • Reduce the number of online waiting threads to reduce the number of context switches.
$ jps
$ jstack 15124 | awk '{print $2$3$4$5}'
22:39:51
threaddumpJavaHotSpot(TM)

#13prio=5os_prio=0tid=0x0000000003377800
RUNNABLE

eventloop"#11prio=5
RUNNABLE
sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(NativeMethod)
sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(WindowsSelectorImpl.java:296)
sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(WindowsSelectorImpl.java:278)
sun.nio.ch.WindowsSelectorImpl.doSelect(WindowsSelectorImpl.java:159)
sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
locked<0x00000000f785d1c8>(aio.netty.channel.nio.SelectedSelectionKeySet)
locked<0x00000000f785ed40>(ajava.util.Collections$UnmodifiableSet)
locked<0x00000000f785e1f0>(asun.nio.ch.WindowsSelectorImpl)
sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedSelectionKeySetSelector.java:62)
io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:765)
io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:413)
io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:909)
java.lang.Thread.run(Thread.java:748)

Thread"#10daemonprio=9
RUNNABLE

CompilerThread3"#9daemonprio=9
RUNNABLE

CompilerThread2"#8daemonprio=9
RUNNABLE

CompilerThread1"#7daemonprio=9
RUNNABLE

CompilerThread0"#6daemonprio=9
RUNNABLE

Listener"#5daemonprio=5
RUNNABLE

Dispatcher"#4daemonprio=9
RUNNABLE

#3daemonprio=8os_prio=1
WAITING(onobjectmonitor)
java.lang.Object.wait(NativeMethod)
waitingon<0x00000000f77185e8>(a
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
locked<0x00000000f77185e8>(ajava.lang.ref.ReferenceQueue$Lock)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

Handler"#2daemonprio=10
WAITING(onobjectmonitor)
java.lang.Object.wait(NativeMethod)
waitingon<0x00000000f7720178>(a
java.lang.Object.wait(Object.java:502)
java.lang.ref.Reference.tryHandlePending(Reference.java:191)
locked<0x00000000f7720178>(ajava.lang.ref.Reference$Lock)
java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

Thread"os_prio=2tid=0x000000000346e800nid=0x4384

deadlock

public class DeadLockDemo {
    private static String A = "A";
    private static String B = "B";
    public static void main(String[] args) {
        new DeadLockDemo().deadLock();
    }

    public void deadLock() {
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                synchronized(A) {
                    try {
                        Thread.currentThread().sleep(200);
                    } catch(InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized(B) {
                        System.out.println("1");
                    }
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            public void run() {
                synchronized(B) {
                    synchronized(A) {
                        System.out.println("2");
                    }
                }
            }
        });

        t1.start();
        t2.start();

    }
}

Several possible causes of deadlock

  • An exception occurred after getting the lock. The lock was not released
  • An exception occurred while releasing the lock

Effects of deadlocks and checking methods

  • Once a deadlock occurs, the service will be unavailable
  • Check for problems through dump threads

Common ways to avoid deadlock

  • Prevent a thread from acquiring multiple locks at the same time
  • Avoid that a thread occupies multiple resources in the lock at the same time, and try to ensure that each lock occupies only one resource
  • Try to use timing lock and use lock. Trylock (timeout) instead of using internal lock mechanism
  • For database locks, the lock and unlock must be in the same database connection, otherwise the unlock will fail

Challenges of resource constraints

What are resource constraints

Resource limitation means that the execution speed of the program is limited by computer hardware resources or software resources during concurrent programming.
For example, the bandwidth of the server is only 2Mb / s, the download speed of a resource is 1MB / s per second, and the system starts 10 threads to download resources
Source, the download speed will not become 10MB / s, so these resource constraints should be considered when concurrent programming. Hardware resource limit
The system has bandwidth upload / download speed, hard disk read-write speed and CPU processing speed. Software resources limit the connection to the database
Number of and socket connections, etc.

Problems caused by resource constraints

In concurrent programming, the principle of speeding up code execution is to turn the serial execution part of the code into concurrent execution. However, if a serial code is executed concurrently, because it is limited by resources, it is still executing serially. At this time, the program will not speed up execution, but will be slower, because it increases the time of context switching and resource scheduling. For example, when I saw a program using multithreading to download and process data concurrently on the office network, the CPU utilization reached 100%, and it could not run and complete the task for several hours. Later, it was modified to single thread, and it was completed in one hour.

How to solve the problem of resource constraints

For hardware resource constraints, you can consider using clusters to execute programs in parallel. Since the resources of a single machine are limited, let the program run on multiple machines. For example, use ODPs, Hadoop or build your own server cluster, and different machines process different data. A machine number can be calculated by “data ID% number of machines”, and then the corresponding machine will process the data. For software resource constraints, consider using resource pools to reuse resources. For example, use the connection pool to reuse the database and socket connections, or establish only one connection when calling the other party’s WebService interface to obtain data.

Concurrent programming under resource constraints

  • Adjust the concurrency of programs according to different resource constraints
  • Downloading files depends on two resources – bandwidth and hard disk read-write speed.
  • When there are database operations, the number of database connections is involved. If the execution of SQL statements is very fast and the number of threads is much larger than the number of database connections, then
    Some threads are blocked waiting for the database connection.