[Multi-threaded high concurrency] 1. Thread creation + thread common method + synchronized bottom layer

 

1. Basic concepts

Process: It is a running activity of a program in a computer on a certain data set. It is the basic unit of the system for resource allocation and scheduling, and it is the foundation of the operating system structure. In contemporary thread-oriented computer architecture, the process is a container for threads. A program is a description of instructions, data and its organization, and a process is the entity of the program. It is a running activity of a program in a computer on a certain data set, the basic unit of the system for resource allocation and scheduling, and the foundation of the operating system structure. A program is a description of instructions, data and its organization, and a process is the entity of the program.

Thread: It  is the smallest unit that the operating system can perform operation scheduling. It is included in the process and is the actual operating unit in the process. A thread refers to a single sequential control flow in a process. Multiple threads can be concurrent in a process, and each thread executes different tasks in parallel.

Several ways to create threads

public class T02_HowToCreateThread {
    static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("Hello MyThread!");
        }
    }

    static class MyRun implements Runnable {
        @Override
        public void run() {
            System.out.println("Hello MyRun!");
        }
    }

    static class MyCall implements Callable<String> {

        @Override
        public String call() throws Exception {
            System.out.println("Hello MyCall");
            return "success";
        }
    }

    public static void main(String[] args) {
        // 第一种
        new MyThread().start();

        // 第二种
        new Thread(new MyRun()).start();

        // 第三种 Lambda
        new Thread(() -> {
            System.out.println("Hello Lambda!");
        }).start();

        // 第四种
        Thread t = new Thread(new FutureTask<String>(new MyCall()));
        t.start();

        // 第五种:线程池。
        ExecutorService service = Executors.newCachedThreadPool();
        service.execute(() -> {
            System.out.println("Hello ThreadPool");
        });
        service.shutdown();
    }

}
//请你告诉我启动线程的三种方式 1:Thread 2: Runnable 3:Executors.newCachedThrad(实际也是用的前两种)

Commonly used methods of threads:

  • join (): call to join the thread that enforcement, other thread is blocked, such as the thread executing the post, and then execute other threads. InterruptedException may be generated by external interruption.
  • sleep(): Put the currently executing thread to sleep (suspend execution) within the specified number of milliseconds. The sleeping thread enters a blocking state.
  • yield(): The thread that calls the yield method will politely let other threads run first. (Release the CPU with a high probability that other threads will run first, and a small probability will run by themselves)
  • Thread.currentThead (): Get the current thread object
  • getPriority(): Get the priority of the current thread
  • setPriority(): Set the priority of the current thread
    • Note: The thread priority is high, and the probability of being scheduled by the CPU is high, but it does not mean that it will run, and there is a small probability of running low-priority threads.
  • isAlive(): Determine whether the thread is active (after the thread calls start, it is active)
  • interrupt(): interrupt thread
  • wait(): Causes the thread to wait and enter a blocked state. This method should only be used in a synchronous method or a synchronous code block
  • notify(): wake up the current thread and enter the running state. This method should only be used in a synchronous method or a synchronous code block
  • notifyAll(): wake up all waiting threads. This method should only be used in a synchronous method or a synchronous code block

Common thread status:

  • New (new state) : When a new thread is created with the new operator, such as new Thread(r), the thread has not yet started running and has not called .start(). This means that its status is new.
  • Runnable (runnable) : Once the start() method is called, it will be executed by the thread scheduler, that is, the operating system executes, and the thread is in the runnable state.
    • Ready state: Ready state means throwing into the waiting queue of the CPU to queue up and waiting for the CPU to run
    • Running state: It is called Running state when it is actually thrown on the CPU to run (when yiled is called, it will go from the Running state to the Ready state, and when the thread scheduler selects the execution, it goes from the Ready state to the Running state)
  • End state: If your thread is successfully executed, it will go in (Note: After the Teamed is finished, you can't return to the new state and call start. When it's over, it's over)
  • TimedWaiting: aWait according to the time, and go back when the time is over, Thread.sleep(time), o.wait(time), t.join(time), LockSupport.parkNanos(), LockSupport.parkUntil() these are all It's about the method of time waiting.
  • , LockSUWaiting waiting: If o.wait(), t.join(), LockSupport.park() are called to enter the Waiting state while running, and notify(), notifyAll(), LockSupport.unpark() are called and then back to Running status
  • Blocked: In the case of synchronizing code blocks, the state will be blocked if the lock is not obtained, and the state is ready when the lock is acquired.

The above states are all managed by the JVM, because the JVM is also managed by the operating system, so it is inseparable between which is the operating system and which is the JVM. JVM is an ordinary program running on the operating system.

 synchronized

  • Guarantee atomicity also guarantee visibility
  • Reentrancy

Lock an object:

public class T {
	
	private int count = 10;
	private Object o = new Object();
	
	public void m() {
		synchronized(o) { //任何线程要执行下面的代码,必须先拿到o的锁
			count--;
			System.out.println(Thread.currentThread().getName() + " count = " + count);
		}
	}
	
}

  synchronized (this) : In view of the need to renew an object each time as described above, it is enough to lock the current object.

public class T {
	
	private int count = 10;
	
	public void m() {
		synchronized(this) { //任何线程要执行下面的代码,必须先拿到this的锁
			count--;
			System.out.println(Thread.currentThread().getName() + " count = " + count);
		}
	}

	public static void main(String[] args) {
		T t = new T();
		t.m();
	}
}

Or it can be written as: (same as above)

public class T {

	private int count = 10;
	
	public synchronized void m() { //等同于在方法的代码执行时要synchronized(this)
		count--;
		System.out.println(Thread.currentThread().getName() + " count = " + count);
	}
}

Static method: there is no this object, you don’t need to create an object to execute this method, but if a synchronized is added to this, it means that synchronized (T.class) here is locked by synchronized (T.class) Is an object of class T

public class T {

	private static int count = 10;
	
	public synchronized static void m() { //这里等同于synchronized(FineCoarseLock.class)
		count--;
		System.out.println(Thread.currentThread().getName() + " count = " + count);
	}
	
	public static void mm() {
		synchronized(T.class) { //考虑一下这里写synchronized(this)是否可以?
			count --;
		}
	}

	public static void main(String[] args) {
		m();
		mm();
	}
}

Supplement: The class load of the same ClassLoader space to the memory is a singleton, but different classloaders are not, and different classloaders cannot access each other, so they can be accessed, which is a singleton.

 

Synchronized can guarantee both atomicity and visibility (provided that the same lock is passed, and the singleton code does not meet this condition)

public class T implements Runnable {

	private /*volatile*/ int count = 10;
	
	public synchronized void run() { 
		count--;
		System.out.println(Thread.currentThread().getName() + " count = " + count);
	}
	
	public static void main(String[] args) {
		
		for(int i=0; i<5; i++) {
			T t = new T();
			new Thread(t, "THREAD" + i).start();
		}
	}
	
}

 

Can synchronous code and asynchronous code be called at the same time:

public class T {

    public synchronized void m1() {
        System.out.println(Thread.currentThread().getName() + " m1 start...");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " m1 end");
    }

    public void m2() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " m2 ");
    }

    public static void main(String[] args) {
        T t = new T();
		
		/*new Thread(()->t.m1(), "t1").start();
		new Thread(()->t.m2(), "t2").start();*/

        new Thread(t::m1, "t1").start();
        new Thread(t::m2, "t2").start();
		
		/*
		//1.8之前的写法
		new Thread(new Runnable() {

			@Override
			public void run() {
				t.m1();
			}
			
		});
		*/
    }
}
t1 m1 start...
t2 m2 
t1 m1 end

If the business permits dirty reads, there is no need to lock the read process.

public class Account {
	String name;
	double balance;
	
	public synchronized void set(String name, double balance) {
		this.name = name;

		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		
		this.balance = balance;
	}
	
	public /*synchronized*/ double getBalance(String name) {
		return this.balance;
	}
	
	
	public static void main(String[] args) {
		Account a = new Account();
		new Thread(()->a.set("zhangsan", 100.0)).start();
		
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println(a.getBalance("zhangsan"));
		
		try {
			TimeUnit.SECONDS.sleep(2);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println(a.getBalance("zhangsan"));
	}
}

synchronized reentrant

A synchronization method can call another synchronization method. A thread can own a lock on an object, and it will still get the lock on the object when it is applied again. That is to say, synchronized acquisition of the lock is reentrant.

public class T {
	synchronized void m1() {
		System.out.println("m1 start");
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		m2();
		System.out.println("m1 end");
	}
	
	synchronized void m2() {
		try {
			TimeUnit.SECONDS.sleep(2);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("m2");
	}

	public static void main(String[] args) {
		new T().m1();
	}
}

The concept that the parent class calls the subclass, the parent class is synchronized, and the subclass must be reentrant when calling super.m, otherwise there will be problems (calling the parent class is the same lock). The so-called re-entry lock means that you keep shackling the yoke after you get the lock. You add several locks, but the same object is locked. If you go to one lock, it will be reduced by 1.

public class T {
	synchronized void m() {
		System.out.println("m start");
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("m end");
	}
	
	public static void main(String[] args) {
		new TT().m();
	}
	
}

class TT extends T {
	@Override
	synchronized void m() {
		System.out.println("child m start");
		super.m();
		System.out.println("child m end");
	}
}

Exception lock : If an exception occurs during the execution of the program, the lock will be released by default. Therefore, in the process of concurrent processing, be careful about exceptions, otherwise inconsistencies may occur.

For example: in the process of a web app, multiple servlet threads access the same resource. If the exception handling is not appropriate, throw an exception in the first thread, and other threads will enter the synchronization code area. Access to the data when the exception occurred.

public class T {
	int count = 0;
	synchronized void m() {
		System.out.println(Thread.currentThread().getName() + " start");
		while(true) {
			count ++;
			System.out.println(Thread.currentThread().getName() + " count = " + count);
			try {
				TimeUnit.SECONDS.sleep(1);
				
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			if(count == 5) {
				int i = 1/0; //此处抛出异常,锁将被释放,要想不被释放,可以在这里进行catch,然后让循环继续
				System.out.println(i);
			}
		}
	}
	
	public static void main(String[] args) {
		T t = new T();
		Runnable r = new Runnable() {

			@Override
			public void run() {
				t.m();
			}
			
		};
		new Thread(r, "t1").start();
		
		try {
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		new Thread(r, "t2").start();
	}
	
}

The underlying principle of synchronized.

  • In the early days of jdk, the underlying implementation of synchronized was a heavyweight, and they would have to find the operating system to apply for locks, which would cause the synchronization efficiency to be very low.
  • After the improvement, there is the concept of lock upgrade (you can refer to: yes, I am the director of the toilet! (2)) . When we use synchronized, what HotSpot has to achieve is really the first one to visit some Lock the thread such as sync (Object). After it comes, now this Object has the mark on the head to record this thread. If only the first thread accesses it, it is actually not locked to this objet. When it is implemented internally, it only records the ID of this thread (bias lock). If there is a thread contention, the bias lock is upgraded to a spin lock. The concept is to use a while loop to spin here (upgrade to a spin lock), and jdk1.6 stipulates that 10 times, it will be upgraded to a heavyweight lock again. , The heavyweight lock is to go to the operating system to apply for resources. This is a process of lock escalation. (The lock upgrade process is irreversible )

Guess you like

Origin blog.csdn.net/zw764987243/article/details/110039026