Black Horse-Concurrent Programming Learning

1. View Process Kill Process
ps -fe | grep java
Or use jps
Top-H-p pid to see how internal threads of the process represented by pid are running
You can also view the thread information of a process using jstack pid
Using jconsole, you can also view thread information for a process (graphical interface)

2. Reasons for thread switching
Time slice exhausted
Higher level thread execution
stw recycling thread execution
The thread itself calls sleep wait join park sychronized, and so on
3. Object Header
Mark Word + klass Word + Alignment Fill

Lock Reentry Unlock for Lightweight Lock
synchronized (obj) Lightweight lock locking requires inserting a lock record Lock Record (Mark Word + Object Reference) in the stack frame of the locking threadAnd set the obj object header Mark Word as a pointer to the lock record through cas. Successful CAS successfully locks, unsuccessful CAS determines if the thread was previously locked, and if not, inserts a Lock record, but Mark Word in Lock Record is no longer a pre-replicated Mark Word but a null value, representing a count.The unlock process requires that MarkWord in LockRecord be set back to MarkWord in obj through cas.

Lightweight lock expansion process
Lock expansion occurs when the lightweight lock CAS setting fails, a corresponding monitor monitor monitor is created for obj, and the owner is set to a running thread (lightweight lock)And block the thread in the EntryList, in a blocked state. After the lightweight lock thread runs the critical zone, it releases the lock as a lightweight lock first, that is, it sets MarkWord in LockRecord in the stack frame through cas, which will obviously fail. This is the process of releasing the heavy lock that will be attempted, that is, it gets obj through object reference,Obj's MarkWord is currently a pointer to a heavyweight lock, so set Monitor's owner to null and wake up blocked threads in EntryList.

Lightweight locks are optimized for spin as well as spin
When a lock object is found to have been occupied by one thread, another thread can spin a certain number of times to wait while trying to acquire the lock. The advantage is the overhead of thread switching avoided when the lock occupies a short time. The disadvantage is that prolonged lock occupancy can cause a large number of threads to spin waiting for the cpu to idle.Adaptive spin refers to the time at which the spin is determined by empirical values, such as the spin time of the thread on the locked object and the state of the lock.

  • Deflection Lock When only one thread has been accessing the critical zone, then obj's MarkWord setting is skewed to the thread id. However, when obj's hashcode method is called, skewed locks are automatically disabled. Because the generated hashcode code needs to be placed in MarkWord in the object header, the thread id can't be put down. You may have questions about this.Why lightweight locks or heavyweight locks don't have this problem, because lightweight locks lock records to save object heads, and heavyweight locks hold Monitor objects.


Wait/notify mechanism

public class Main {
    public static void main(String[] args) throws IllegalAccessException {

        Package p = new Package(0);

        for(int i = 0;i < 3;i++){
            new Thread(()->{
                try {
                    while(true){
                        p.produce();
                        Thread.sleep(2000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        for(int i = 0;i < 3;i++){
            new Thread(()->{
                try {
                    while(true){
                        p.consume();
                        Thread.sleep(2000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }


    }
    static class Package{
        private int count;
        private Object Lock = new Object();

        public Package(int count) {
            this.count = count;
        }
        public void consume() throws InterruptedException {
            synchronized (Lock){
                while(count == 0){
                    Lock.wait();
                }
                count--;
                System.out.println("Consumer consumption 1, currently"+count);
                Lock.notifyAll();
            }

        }
        public void produce() throws InterruptedException {
            synchronized (Lock){
                while(count == 10){
                    Lock.wait();
                }
                count++;
                System.out.println("Producer produces 1, currently"+count);
                Lock.notifyAll();
            }
        }
    }




}

Differences between park unpark and wait notify
1. wait notify must be used with Monitor
2. The park unpark unit of action is a thread, even if a thread waits or wakes a specific thread wait notify, it will wake the thread in Watset of Monitor randomly. park unpark wakes a specific thread
3. Notfy only works when a thread calls wait to wake up the wait thread. park unpark can unpark(thread) before park also immediately resume running the park thread.

park unpark principle

Thread Conversion


Deadlock detection tools
jps

D:\worksapce\LeetCode\src\main\java\com\gaojl>jps
17344 Main
22496 RemoteMavenServer36
46672
65600 JConsole
40676 Launcher
16456 Jps

D:\worksapce\LeetCode\src\main\java\com\gaojl>jstack 17344
2021-09-09 09:25:18
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.221-b11 mixed mode):

"RMI TCP Connection(5)-169.254.116.19" #23 daemon prio=5 os_prio=0 tid=0x000000001f40a800 nid=0x2734 in Object.wait() [0x00000000209ec000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076f680f10> (a com.sun.jmx.remote.internal.ArrayNotificationBuffer)
        at com.sun.jmx.remote.internal.ArrayNotificationBuffer.fetchNotifications(ArrayNotificationBuffer.java:449)
        - locked <0x000000076f680f10> (a com.sun.jmx.remote.internal.ArrayNotificationBuffer)
        at com.sun.jmx.remote.internal.ArrayNotificationBuffer$ShareBuffer.fetchNotifications(ArrayNotificationBuffer.java:227)
        at com.sun.jmx.remote.internal.ServerNotifForwarder.fetchNotifs(ServerNotifForwarder.java:274)
        at javax.management.remote.rmi.RMIConnectionImpl$4.run(RMIConnectionImpl.java:1270)
        at javax.management.remote.rmi.RMIConnectionImpl$4.run(RMIConnectionImpl.java:1268)
        at javax.management.remote.rmi.RMIConnectionImpl.fetchNotifications(RMIConnectionImpl.java:1274)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
        at sun.rmi.transport.Transport$1.run(Transport.java:200)
        at sun.rmi.transport.Transport$1.run(Transport.java:197)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
        at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$5/951671104.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

"RMI TCP Connection(4)-169.254.116.19" #22 daemon prio=5 os_prio=0 tid=0x000000001f406000 nid=0xa61c runnable [0x00000000208ed000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
        - locked <0x000000076f68a268> (a java.io.BufferedInputStream)
        at java.io.FilterInputStream.read(FilterInputStream.java:83)
        at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:555)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$5/951671104.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

"RMI TCP Connection(3)-169.254.116.19" #21 daemon prio=5 os_prio=0 tid=0x000000001f4e9000 nid=0x16a4 runnable [0x00000000207ee000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
        - locked <0x000000076f690df0> (a java.io.BufferedInputStream)
        at java.io.FilterInputStream.read(FilterInputStream.java:83)
        at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:555)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$5/951671104.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

"JMX server connection timeout 19" #19 daemon prio=5 os_prio=0 tid=0x000000001f542000 nid=0x5f94 in Object.wait() [0x00000000204ef000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076f698178> (a [I)
        at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168)
        - locked <0x000000076f698178> (a [I)
        at java.lang.Thread.run(Thread.java:748)

"RMI Scheduler(0)" #18 daemon prio=5 os_prio=0 tid=0x000000001f52d000 nid=0x2910 waiting on condition [0x00000000203ef000]
   java.lang.Thread.State: TIMED_WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x000000076f6a0188> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

"RMI TCP Accept-0" #16 daemon prio=5 os_prio=0 tid=0x000000001e639800 nid=0xca8c runnable [0x000000001fe7e000]
   java.lang.Thread.State: RUNNABLE
        at java.net.DualStackPlainSocketImpl.accept0(Native Method)
        at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
        at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
        at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
        - locked <0x000000076f6a82b0> (a java.net.SocksSocketImpl)
        at java.net.ServerSocket.implAccept(ServerSocket.java:545)
        at java.net.ServerSocket.accept(ServerSocket.java:513)
        at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:52)
        at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:405)
        at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:377)
        at java.lang.Thread.run(Thread.java:748)

"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x0000000002af3800 nid=0xbe58 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"b" #13 prio=5 os_prio=0 tid=0x000000001f3d2800 nid=0x3890 waiting for monitor entry [0x000000001fd2e000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.gaojl.Main.lambda$main$1(Main.java:37)
        - waiting to lock <0x000000076f6b02f0> (a java.lang.Object)
        - locked <0x000000076f6b0300> (a java.lang.Object)
        at com.gaojl.Main$$Lambda$2/999966131.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

"a" #12 prio=5 os_prio=0 tid=0x000000001f3cf800 nid=0x373c waiting for monitor entry [0x000000001fc2f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.gaojl.Main.lambda$main$0(Main.java:29)
        - waiting to lock <0x000000076f6b0300> (a java.lang.Object)
        - locked <0x000000076f6b02f0> (a java.lang.Object)
        at com.gaojl.Main$$Lambda$1/2093631819.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

"Service Thread" #11 daemon prio=9 os_prio=0 tid=0x000000001e532800 nid=0x47fc runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread3" #10 daemon prio=9 os_prio=2 tid=0x000000001e49a000 nid=0x5288 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x000000001e43c000 nid=0x59fc waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x000000001e439800 nid=0xf61c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x000000001e483000 nid=0x4410 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x000000001e3cc000 nid=0x66f8 runnable [0x000000001ed2e000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
        - locked <0x000000076f6b8318> (a java.io.InputStreamReader)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:161)
        at java.io.BufferedReader.readLine(BufferedReader.java:324)
        - locked <0x000000076f6b8318> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine(BufferedReader.java:389)
        at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001e3b5000 nid=0xaa94 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001e3b1000 nid=0x12e78 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001e3a1800 nid=0x3f54 in Object.wait() [0x000000001e97f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076f6b0798> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
        - locked <0x000000076f6b0798> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001e3a0800 nid=0x9b54 in Object.wait() [0x000000001e87f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076f6b8308> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x000000076f6b8308> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=2 tid=0x000000001c5a9800 nid=0xbd08 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002b09000 nid=0x69f8 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002b0a800 nid=0xd7ec runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002b0c000 nid=0xdd1c runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002b0e800 nid=0x28ac runnable

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x0000000002b11000 nid=0x6948 runnable

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x0000000002b12000 nid=0x6958 runnable

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x0000000002b15000 nid=0x11c10 runnable

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x0000000002b16800 nid=0x100a0 runnable

"VM Periodic Task Thread" os_prio=2 tid=0x000000001e536800 nid=0xfdb4 waiting on condition

JNI global references: 233


Found one Java-level deadlock:
=============================
"b":
  waiting to lock monitor 0x0000000002bebc18 (object 0x000000076f6b02f0, a java.lang.Object),
  which is held by "a"
"a":
  waiting to lock monitor 0x0000000002bee6b8 (object 0x000000076f6b0300, a java.lang.Object),
  which is held by "b"

Java stack information for the threads listed above:
===================================================
"b":
        at com.gaojl.Main.lambda$main$1(Main.java:37)
        - waiting to lock <0x000000076f6b02f0> (a java.lang.Object)
        - locked <0x000000076f6b0300> (a java.lang.Object)
        at com.gaojl.Main$$Lambda$2/999966131.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)
"a":
        at com.gaojl.Main.lambda$main$0(Main.java:29)
        - waiting to lock <0x000000076f6b0300> (a java.lang.Object)
        - locked <0x000000076f6b02f0> (a java.lang.Object)
        at com.gaojl.Main$$Lambda$1/2093631819.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

reentrantLock and synchronized

reentrantLock supports fair locks and multiple df-piece variables compared to synchronized.
Both synchronized and reentrantlock support reentrant.

 ReentrantLock lock = new ReentrantLock();
        lock.lock();
        try{
            //Critical zone
        }finally {
            lock.unlock();
        }

reentrantLock responds to interrupt lock.lockInterruptbily()
reentrantLock timed out to get lock.tryLock(time);

3 threads print ABC alternately 5 times

public class Main {
    public static void main(String[] args)  {
        ReentrantLock lock = new ReentrantLock();
        WaitNotify wn = new WaitNotify(1,3);
        new Thread(()->{
            wn.print("a",1);
        },"t1").start();
        new Thread(()->{
            wn.print("b",2);
        },"t2").start();
        new Thread(()->{
            wn.print("c",3);
        }).start();
    }
}
class WaitNotify{
    int printFlag;
    int looptimes;
    public WaitNotify(int printFlag,int looptimes) {
        this.printFlag = printFlag;
        this.looptimes = looptimes;
    }
    public void print(String str,int flag){
        for (int i = 0; i < looptimes ; i++) {
            synchronized (this){
                try{
                    while(printFlag != flag){
                        this.wait();
                    }
                    System.out.println(str);
                    printFlag = next(printFlag,looptimes);
                    this.notifyAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private int next(int now,int limit) {
        if(now + 1 <= limit){
            return  now+1;
        }else{
            return 1;
        }
    }
}
public class Main {
    public static void main(String[] args)  {
        AwaitSignal as = new AwaitSignal(3);
        Condition a = as.newCondition();
        Condition b = as.newCondition();
        Condition c = as.newCondition();
        new Thread(()->{
            as.print("a",a,b);
        }).start();
        new Thread(()->{
            as.print("b",b,c);
        }).start();
        new Thread(()->{
            as.print("c",c,a);
        }).start();

        as.lock();
        try{
            a.signal();
        }finally {
            as.unlock();
        }
    }
}
class AwaitSignal extends ReentrantLock{
    private int looptimes;
    public AwaitSignal(int looptimes){
        this.looptimes = looptimes;
    }
    public void print(String str,Condition cur,Condition next){
        for (int i = 0; i < looptimes; i++) {
            lock();
            try{
                cur.await();
                System.out.print(str);
                next.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                unlock();
            }
        }
    }
}

Instruction Rearrangement Optimization

Instruction reordering refers to the possible reordering of instructions by the compiler and CPU during program execution for performance reasons
cpu-level instruction rearrangement optimization (refers to analysis execution)Each instruction is completed by several subtasks. If one instruction is executed and another is executed, the clock cycle required will be very long. Assuming an instruction needs 3 clock cycles, two instructions need 6. In fact, the fetch part will be idle after the fetch value instruction is executed, and then the fetch operation of the second instruction can be executed.At this point, multiple instructions achieve a parallel effect. Instruction rearrangement is a non-dependent rearrangement of two instructions, such as a = 1, b=2 C = a + B.

In DCL singleton mode, Single is modified by volatile and added without volatile so single = new Single() Procedures can be divided into load link initialization where initialization refers to the execution of a class construction method that sets the value of the class variable to the default value. The construction method initialization is then invoked. The construction method initialization is then assigned to the variable. An instruction rearrangement occursAn uninitialized object will be used by other threads, and errors will occur when other threads use uninitialized objects.

	Class Single{
		private volatile static  Single single;
		private Single(){}
		public static Single getInstance(){
			if(single == null){
				synchronized(Single.class){
					if(single == null){
						single = new Single();
						return single;
					}
				}
			}
			return single
		}
	}

Read-write barrier Read-before-read barrier guarantees that the read instructions behind the read barrier will not be optimized by the compiler before the read barrier.
The write barrier after the write barrier writes instructions ensures that the write instructions before the write barrier are not optimized after the write barrier.

happens-before principle

Happens-beforeDefines the visibility of write operations on shared variables to other threads. For example, changes to shared variables made by threads running first will be visible to other threads

cas and volatile

The instruction used at the bottom of CAS settings is cmpexchg. He needs the expected value of the variable to be compared with the value in main memory. So volatile needs to be used with cas.

cas is based on optimistic locking and fails to retry instead of blocking threads on the monitor's entryList as synchronized does. cas is unlocked and concurrent without blocking. However, if too many retries will inevitably affect efficiency, it is suitable for situations where threads are fewer and cpu cores are more.

final principle

Initialization of non-final variables is divided into clinit and init phases. As a result, there will be instances where other threads get uninitialized variables. final variables are assigned directly after initialization and then added a write barrier. This allows other threads to get the latest values.

Custom Thread Pool

public class Main {


    public static void main(String[] args) {
        ThreadPool tp = new ThreadPool(2,TimeUnit.MILLISECONDS,1000,1,((taskQueue, task) -> {
            //throw new RuntimeException("blocked queue full");throw
            taskQueue.offer(task,1000,TimeUnit.MILLISECONDS);
        }));
        for(int i = 0;i < 5;i++){
            int j = i;
            tp.execute(()->{
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("task"+j);
            });
        }

    }

    @FunctionalInterface
    interface RejectPolicy<T> {
        void reject(BlockingQueue<T> taskQueue, T task);
    }

    class Person {
        Integer id;
        String name;

        public Person(Integer id, String name) {
            this.id = id;
            this.name = name;
        }

        public Integer getId() {
            return id;
        }

        public String getName() {
            return name;
        }
    }

    static class ThreadPool {

        private BlockingQueue<Runnable> taskQueue;

        HashSet<Worker> workers = new HashSet();

        private int coreSize;
        private TimeUnit timeUnit;
        private long timeout;
        private RejectPolicy<Runnable> rejectPolicy;


        public ThreadPool(int coreSize, TimeUnit timeUnit, long timeout, int queueCapacity, RejectPolicy<Runnable> rejectPolicy) {
            this.coreSize = coreSize;
            this.timeUnit = timeUnit;
            this.timeout = timeout;
            this.taskQueue = new BlockingQueue<>(queueCapacity);
            this.rejectPolicy = rejectPolicy;
        }

        public void execute(Runnable task) {
            Worker worker = null;

            synchronized (workers) {
                if (workers.size() < coreSize) {
                    worker = new Worker(task);
                    System.out.println("Create worker thread"+worker);

                    workers.add(worker);
                    System.out.println("Work Threads"+worker+"Execute Tasks");
                    worker.start();
                } else {
                    //Put task in blocking queue
                   // taskQueue.put(task);
                    rejectPolicy.reject(taskQueue,task);

                }
            }


        }

        class Worker extends Thread {

            private Runnable task;

            public Worker(Runnable task) {
                this.task = task;
            }

            @Override
            public void run() {
                while (task != null || (task = taskQueue.poll(timeout,timeUnit)) != null) {
                    try {
                        try {
                            task.run();
                        } catch (Exception e) {

                        }
                    } finally {
                        task = null;
                    }
                }
                synchronized (workers) {
                    System.out.println("remove");
                    workers.remove(this);
                }


            }
        }


    }

    static class BlockingQueue<T> {
        private Deque<T> queue = new ArrayDeque<>();

        private Integer capacity;

        public BlockingQueue(Integer capacity) {
            this.capacity = capacity;
        }

        private ReentrantLock lock = new ReentrantLock();
        private Condition full = lock.newCondition();
        private Condition empty = lock.newCondition();

        //Blocking Get Task
        public T take() {
            lock.lock();
            try {
                while (queue.isEmpty()) {
                    empty.await();
                }

                T t = queue.removeFirst();
                full.signal();
                return t;
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
            return null;

        }

        public T poll(long timeOut, TimeUnit timeUnit) {

            lock.lock();
            try {
                long nanos = timeUnit.toNanos(timeOut);
                while (queue.isEmpty()) {
                    if(nanos <= 0){
                        return null;
                    }
                    nanos = empty.awaitNanos(nanos);
                }
                T t = queue.removeFirst();
                full.signal();
                return t;
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
            return null;

        }

        public void put(T t) {
            lock.lock();
            try {
                while (queue.size() == capacity) {
                    try {
                        full.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                queue.offerLast(t);
                empty.signal();
            } finally {
                lock.unlock();
            }
        }

        public boolean offer(T task, long timeOut, TimeUnit timeUnit) {
            lock.lock();
            long nanos = timeUnit.toNanos(timeOut);
            try {
                while (queue.size() >= capacity) {
                    if (nanos <= 0) {
                        System.out.println("Task failed to join queue"+task);
                        return false;
                    }
                    nanos = full.awaitNanos(nanos);
                }
                queue.addLast(task);
                empty.signal();


            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
            return true;
        }
    }
}

Thread Pool Threads

cpu intensive: cpu cores + 1
io intensive: cpu core count X cpu utilization X (wait time + cpu run time) / cpu run time

Tags: Java Concurrent Programming

Posted on Sat, 11 Sep 2021 14:04:12 -0400 by burningkamikaze