JDK source code analysis Shu Java Thread

Thread related concepts

A thread is the smallest unit of allocation of system resources, which is included in the process, the actual operation of the unit process. JVM allows applications running simultaneously executing a plurality of threads, each thread has a priority, with higher priority thread precedence over lower-priority thread execution

In Java threads are divided into two categories: User Thread(用户线程),Daemon Thread(守护线程)

In the JVM when it will start calling the main function, the thread where the main function is that a user thread, the new thread in this thread is the default user thread, but by Thread.setDaemon (true) can be set daemon threads (to be in Thread. start () before the call). JVM nanny daemon thread is that all non-daemon threads, the most typical application is a daemon thread GC (garbage collector)

As long as the current instance of the JVM does not end in any surviving a non-threaded daemon, a daemon thread on the work of all of a user when the end of the last thread in the JVM, JVM as the guardian of the thread ends together


Thread creation mode

There are two ways to create threads: 继承 Thread 类,实现 Runnable 接口

Thread class itself is done by implementing Runnable interface created. You can specify a name for the thread when a thread is created, the name can be repeated. If the name is not specified when a thread is created, the switch will generate a new name

Inheritance Thread class is created and started:

     class PrimeThread extends Thread {
         long minPrime;
         PrimeThread(long minPrime) {
             this.minPrime = minPrime;
         }

         public void run() {
             // compute primes larger than minPrime
         }
     }
复制代码
     PrimeThread p = new PrimeThread(143);
     p.start();
复制代码

Runnable interface to create and implement start:

     class PrimeRun implements Runnable {
         long minPrime;
         PrimeRun(long minPrime) {
             this.minPrime = minPrime;
         }

         public void run() {
             // compute primes larger than minPrime
         }
     }
复制代码
     PrimeRun p = new PrimeRun(143);
     new Thread(p).start();
复制代码

Thread state changes

State of the thread can Threadbe found in the source category, a total of NEWsix: RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED, ,

    public enum State {

        NEW, // 尚未启动状态

        RUNNABLE, // 可运行状态,但它可能还在等待处理器资源分配

        BLOCKED, // 阻塞状态

        WAITING, // 等待状态,等待另一个线程执行完毕

        TIMED_WAITING, // 定时等待状态

        TERMINATED; // 终止状态,线程已执行完毕
    }

复制代码


Thread class source of Key Method

Thread.start () : start the thread

When you call start (), will first check whether it is the first time to start this thread, that is threadStatus == 0, if the threadStatus != 0explanation for the current repeat start, which is not allowed, the thread will throw an exception error statusIllegalThreadStateException

By After checking, the current thread will thread group added instance of the object group, after passing through the native method start0()execution of the thread operation is started. After starting the completion threadStartFailed()within the removal was performed, the release of resources

    public synchronized void start() {

        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                ···
            }
        }
    }

    private native void start0();
复制代码

Thread.stop () : forced stop thread execution

This method is not safe, it may produce unpredictable results, like shut off the power supply by, rather than through the normal shutdown operation is completed, the same result, the process is completely different

Calls stop()will throw an ThreadDeathexception this time the runmethod will perform over, the thread would cease, and this is the end of the thread to throw an exception

After the release of all the locks held by the sub-thread, general any code block lock, it is to protect the consistency of the data, if the call thread.stop (after) resulted in the thread about all the locks held the sudden release (uncontrollable), then it is possible to render the protected data inconsistency, other threads in the use of these data is corrupted, it may lead to some very strange application error

    @Deprecated
    public final void stop() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            checkAccess();
            if (this != Thread.currentThread()) {
                security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
            }
        }

        if (threadStatus != 0) {
            resume(); // Wake up thread if it was suspended; no-op otherwise
        }

        stop0(new ThreadDeath());
    }

    @Deprecated
    public final synchronized void stop(Throwable obj) {
        throw new UnsupportedOperationException();
    }
复制代码

Thread.run () : The actual code running thread block

Note that, if you want to start a thread, direct call run()method is invalid, it will not produce any practical results

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
复制代码

Thread.interrupt () : modify the interrupt state to achieve a reasonable and safe interrupts the current thread

stop()The method can also be interrupted thread, but it was immediately terminated, will lead to some unknown problem, so there have been interrupt()methods, which can be achieved with a conditional terminate the thread, making data security guaranteed

To realize the thread is interrupted, interrupt()need to meet isInterrupted()or interrupted()used together, these two methods can be acquired interrupt flag is true, we can do after obtaining the appropriate treatment. Call isInterrupted()returns the interrupt status but does not restore the state, interrupted()will return interrupt status and clears the interrupt status, according to the actual needs of the business were used to

    public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }
复制代码
    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }
复制代码
    public boolean isInterrupted() {
        return isInterrupted(false);
    }
复制代码

Thread.yield () : suspend execution of the current thread, allowing other threads to execute a cpu (but may be ignored)

In fact, if you want yield()to play its role, we need to match the thread 优先级used, its exact operating procedure is to detect whether there is the same as the current priority threads can be run in the same state, if any, to put the CPU tenure this thread, or continue to run the original thread. So yield () method is called "concession", which give the opportunity to run other threads of equal priority.

    public static native void yield();
复制代码

Thread.wait () / Thread.wait (Long) : the thread calls this method to release a shared resource lock, then withdraw from the run state and enters the waiting queue, until they were awakened again or wait N millisecond timer, if no notice timeouts return

wait()It belongs to the Objectobject. When first obtain a lock, a general method of synchronization on the synchronization code or block ( synchronized) by notify()or notifyAll()wakeup

    public final void wait() throws InterruptedException {
        wait(0);
    }

    public final native void wait(long timeout) throws InterruptedException;
复制代码

Thread.join () / Thread.join (Long) : After waiting for the end of the thread, and then continue

Its role is to call to join the thread priority execution thread currently executing block until the call to join the thread that completes or is interrupted, mainly for the interaction between threads

    public final void join() throws InterruptedException {
        join(0);
    }

    public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }
复制代码

Thread.sleep (Long) : the current thread suspended within the specified time

Calling this thread object pausing interrupt()will wake up the thread and throw InterruptedException, then proceed

    public static void sleep(long millis, int nanos)
    throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        sleep(millis);
    }
复制代码

Thread.notify () / Thread.notifyAll () : wake up the thread is waiting for state

Common usage scenario is a thread A calls object B of the wait () method to enter the wait state, and another thread calls notify C object B () / notifyAll () method, after receipt of notice of withdrawal from the thread A queue waiting to enter runnable state, and further subsequent operations. A two threads C and to complete interactive objects by B, and the relationship on the object wait () and notify () / notifyAll () method is the same as if the switching signal, waiting for the completion of the interaction between the party and notify party jobs.

notify() Wake random waiting queue for the same shared resource threads, this thread exits back to the waiting queue, runnable

notifyAll() All threads are waiting to wake up all waiting in the queue the same shared resources, all the exit queue, runnable, the highest priority is started

   public final native void notify();

   public final native void notifyAll();
复制代码

Thread class source code other methods

currentThread () : Returns the currently executing thread object reference

    /**
     * Returns a reference to the currently executing thread object.
     *
     * @return  the currently executing thread.
     */
    public static native Thread currentThread();
复制代码

This is a Native method, out of this method is native functions, are implemented using C / C ++ language, and is compiled into DLL, the java to call, to achieve Functions in the DLL, the JDK source code does not contain so we do not see. This is the underlying mechanism of java, java is actually calling different native methods on different platforms to achieve access to the operating system.

    System.out.println("对象信息:" + Thread.currentThread());

    //// 输出结果
    对象信息:Thread[main,5,main]
复制代码

getId () : Returns the ID of the thread

    /**
     * Returns the identifier of this Thread.  The thread ID is a positive
     * <tt>long</tt> number generated when this thread was created.
     * The thread ID is unique and remains unchanged during its lifetime.
     * When a thread is terminated, this thread ID may be reused.
     *
     * @return this thread's ID.
     * @since 1.5
     */
    public long getId() {
        return tid;
    }
    
    // tid 在 Thread 的 init 中赋值
    ···
    tid = nextThreadID();
    ···

    // tid 等于 threadSeqNumber,而 threadSeqNumber 专门被用来生成线程的 ID
    private static synchronized long nextThreadID() {
        return ++threadSeqNumber;
    }
复制代码

ID is a long thread type, generated by nextThreadID method, nextThreadID method is thread-safe (synchronized modified), every time you create a new thread ID tid ++ and assigned to

    System.out.println("线程  ID:" + Thread.currentThread().getId());

    //// 输出结果(main方法中调用)
    线程  ID:1
复制代码

** getName (): ** Gets the name of the thread

    /**
     * Returns this thread's name.
     *
     * @return  this thread's name.
     * @see     #setName(String)
     */
    public final String getName() {
        return name;
    }
复制代码

Thread name of type String, the default is Thread-N (N: order of threads created, starting from 0). Of course, the Thread class also provides two methods to modify the name, namely: new Thread ( "name") or Thread.setName ( "name")

	Thread threadTest01 = new Thread();
	System.out.println("线程名称:" + threadTest01.getName());
	
	Thread threadTest02 = new Thread();
	System.out.println("线程名称:" + threadTest02.getName());
	
	Thread threadTest03 = new Thread("我有名字,我叫 T03");
	System.out.println("线程名称:" + threadTest03.getName());
	
	Thread threadTest04 = new Thread();
	threadTest04.setName("我有名字:我叫 T04");
	System.out.println("线程名称:" + threadTest04.getName());

    //// 输出结果
    线程名称:Thread-0
    线程名称:Thread-1
    线程名称:我有名字,我叫 T03
    线程名称:我有名字:我叫 T04

复制代码

getPriority () : Gets the thread priority

    /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;

    // 线程优先级在初始化(init)时设置,默认是等同于父线程优先级
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        ...
        Thread parent = currentThread();
        ···
        this.priority = parent.getPriority();
        ···
    }

    /**
     * Returns this thread's priority.
     *
     * @return  this thread's priority.
     * @see     #setPriority
     */
    public final int getPriority() {
        return priority;
    }
复制代码

The default thread priority of the parent thread priority: this.priority = parent.getPriority();. The execution order priority threads can not determine the thread, but the probability of obtaining a higher CPU resources greater priority

A thread's priority can setPriority (int newPriority) is provided, the parameter range of 1 - 10 defaults to 5

    public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }
复制代码

Note that, when setting thread priorities can not be greater than the maximum priority, otherwise it will happen throw new IllegalArgumentException();, it can not be greater than the highest priority thread that group, otherwise it will be reset to the priority of the thread group newPriority = g.getMaxPriority();, as follows:

public static void main(String[] args) {
	
	ThreadMethods main = new ThreadMethods();
	Thread t01 = main.new MyThread01();
	Thread t02 = main.new MyThread02();
	
	t01.setPriority(Thread.MAX_PRIORITY);
	t02.setPriority(Thread.MIN_PRIORITY);
	
	t02.start();
	t01.start();
}

/**
 * @des 测试线程 01
 * */
class MyThread01 extends Thread{
	public void run() {
		super.run();
		
		for(int i = 0 ; i < 10 ; i++ ){
			System.out.println("MyThread01:" + i);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}
} 

/**
 * @des 测试线程 02
 * */
class MyThread02 extends Thread{
	public void run() {
		super.run();
		
		for(int i = 0 ; i < 10 ; i++ ){
			System.out.println("MyThread02:" + i);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}
} 

//// 输出结果
MyThread01:0
MyThread02:0
MyThread02:1
MyThread01:1
MyThread02:2
MyThread01:2
MyThread02:3
MyThread01:3
MyThread01:4
MyThread02:4
MyThread01:5
MyThread02:5
MyThread01:6
MyThread02:6
MyThread01:7
MyThread02:7
MyThread01:8
MyThread02:8
MyThread01:9
MyThread02:9
复制代码

Thread Common Problems

The reason deadlock and how to avoid and resolve

The reason for the deadlock in the case of multiple simultaneous threads are blocked, or all of them are waiting for a resource to be released, because the thread is blocked infinite, the rest of this thread and other resources can not be released, so the program can not then continue normal operation (For a vivid chestnut: a priceless treasure chest loaded with two keys needed to open, two people have a key, but are waiting for each other to hand over the keys, but they who do not and to hand over their keys has been stalemate)

Why deadlock?

Deadlock must meet the following four conditions, as long as any of the conditions is not satisfied, the deadlock will not occur

  • Mutually exclusive conditions: Thread the requirements of the allocated resources in exclusive control, that is, within a period of time a resource is only one process at this time if there are other processes that share the resource request then the request process can only wait...
  • Not deprivation: resources obtained in the process before completion is not used, other processes can not be forcibly taken away, that is obtained only by the resources of its own thread to release (only active release).
  • Request and keeping conditions: thread already holds at least one resource, but proposed a new resource request, the resource has been occupied by other threads, this time requesting thread is blocked, but the resources that they have available to keep hold.
  • Loop wait condition: there is a waiting loop chain thread resource, resource chain each thread has been obtained by the next thread while the chain requested.

Deadlock conditions are summarized:

  1. At least one resource can not be shared
  2. At least one task must hold a resource and waiting to acquire a resource held by another other tasks
  3. Resources can not be preempted task
  4. There must wait cycle

How to avoid and resolve a deadlock?

1, to avoid nesting lock This is the most common cause of deadlock, if you already have a resource, please avoid locking other resources. If only one object lock, it is almost impossible deadlock situation, such as the following modifications to the code of the upper portion of the nested loop, where deadlock is avoided:

public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " acquiring lock on " + obj1);
        synchronized (obj1) {
            System.out.println(name + " acquired lock on " + obj1);
            work();
        }
        System.out.println(name + " released lock on " + obj1);
        System.out.println(name + " acquiring lock on " + obj2);
        synchronized (obj2) {
            System.out.println(name + " acquired lock on " + obj2);
            work();
        }
        System.out.println(name + " released lock on " + obj2);

        System.out.println(name + " finished execution.");
    }
复制代码

2, only part of the lock needs only managed to lock resources needed, such as in the above program, we locked up the complete object resources, but if we only need one field, then we should just lock that particular field and not a complete object

3, to avoid waiting indefinitely if two threads using a thread join wait indefinitely for each other will result in a deadlock, we can set the maximum waiting time to avoid this.

JAVA difference in the type and locks

During code execution, some of the data required to ensure that the exclusive control of the correctness of the final results, a mechanism is needed to ensure that the data is not modified outside locked during execution, this mechanism is a locking mechanism

Meanwhile, according to the characteristics of the lock, design, different states, and can not be strictly classified as follows:

Lock fair / unfair Lock

Fair lock means that multiple threads in order to apply the lock to get the lock, the lock is unfair not completely random order, may cause priority inversion or hunger show

Synchronized fair non-locking, can be determined by the constructor of ReentrantLock fair or unfair lock latch, a lock mode is a non fair

Throughput performance of non-arm lock to lock more than fair

Reentrant lock

Also known as recursive locks, refers to the time in the same thread acquires the lock of the outer layer of the method, the method will automatically get into the inner lock

Synchronized and ReentranLock are reentrant lock, deadlock can be avoided to some extent

Exclusive lock / shared lock

Exclusive lock means the lock can only be held by a county, shared lock means the lock can be thought of as more holders

Synchronized and ReentranLock are exclusive lock. ReadWriteLock read lock is a shared lock, write lock is an exclusive lock. ReentrantLock exclusive lock and a shared lock is achieved by AQS

Mutex / read-write lock

= Mutex lock exclusive, shared locks = write lock. Mutex essence ReentrantLock, read-write locks essence ReadWriteLock

Lock optimistic / pessimistic locking

They do not belong to a specific lock classification, but look at the angle of concurrent synchronization

Optimistic locking for concurrency think the same data is not going to happen to modify, update data when using back constantly try to update, considered optimistic locking concurrency is not locked all right

Pessimistic locking think must happen for the same data modification of concurrent operations, so for concurrent operation, pessimistic locking lock unified data take the form of, because pessimistic locking think there will be an unlocked operational problems

Pessimistic locking operation is very suitable for many scenarios, optimistic locking for a lot of reading and writing scene, unlocked can greatly improve performance

Segmented lock

In fact, a lock of strategy, not a specific lock. The concurrent ConcurrentHashMap efficient implementation is achieved by the concurrent operation of the lock segment in the form of

When you want to put the entire hashMap elements are not locked, but first it has to be placed by hashCode know which segment, then the segment were locked, so long as when placed in different segments of the multi-threaded elements is put to do true parallel insert, but when you need to get all the statistical size segment lock to be calculated

Lock segment is designed to refine the lock granularity

Biased locking / lock lightweight / heavyweight lock

This is in accordance with the lock to summarize the state, and against the Synchronized. java 1.6 In order to reduce acquire the lock is released lock performance problems caused by the introduction of a state, it will compete with the escalating situation, the lock can upgrade but can not downgrade means that bias the lock escalation can not lock into a lightweight retracement this upgrade not downgrade strategy purpose is to improve the efficiency of live lock and release the lock

Spinlocks

In fact, with respect to the concept of a mutex, mutex thread enters WAITING state and RUNNABLE state of fantasy involving context switching, CPU preemption overhead, spin thread lock has been RUNNABLE state, has been locked loop detection flag that bit mechanism is not repeated, but the spin lock lock the entire consumption CPU, although lower than the initial cost of the mutex lock hold time but with the lock overhead is linear growth

Interruptible lock

Synchronized is not interrupted, Lock is interruptible

Here interruptible built blocked waiting for an interrupt, the operation is not interrupted


Synchronized synchronous lock principle

This article deals continuously updated thread-related knowledge, learn together to address gaps enjoyment!

Guess you like

Origin juejin.im/post/5d4d41945188252d336992d4