The memory model of the thread
32-bit operating system addressing space is 2 of 32, that is, 4GB of addressing space, the system in this 4GB space to divide the 1GB of space for the system-specific, known as the kernel space, with the highest permissions; the remaining 3GB space is the user space (the average JVM can only use the maximum memory 2GB), Only the memory address of the current thread partition can be accessed. When a user thread needs to access hardware resources, it needs to delegate the kernel thread to access it, which involves the CPU context switching between user mode and kernel mode. As a result, you need to avoid unnecessary user-mode and kernel-mode switching when using threads or processes.
A process is the smallest unit of resource management, and a thread is the smallest unit of CPU scheduling. A thread is a more lightweight scheduling execution unit than a process, and threads can share resources within the same process (memory address, file I/O, etc.) and are the basic unit of the CPI Independent Dispatch. There are three main ways to implement threading:
#1 the use of a kernel thread to support a user process, and the user process to support multi-threading, the advantage is that thread switching occurs in user mode, the disadvantage is that the thread is completely transparent to the system kernel, all resource scheduling needs to be processed by the user process, and because there is only one kernel thread, So only one CPU resource can be used (multicore CPUs are completely out of the line) and if a hardware I/O operation is blocked, the thread's hardware I/O is blocked.
#2 use kernel thread (Kernel level thread) one-to-one support lightweight process (light Weight process), a lightweight process corresponding to a thread, the advantage is that can maximize the use of multi-CPU performance, multi-tasking at the same time, However, the biggest disadvantage is that because the thread blocking or wake-up requires the system kernel for processing, the program needs to constantly switch between user mode and kernel mode, increasing the cost of switching.
#3使用内核线程 (Kernel level Thread) supports a lightweight process (light Weight process) one-to-one, and uses lightweight processes for many-to-many support for user threads, which is the advantage of mixing the previous two implementations. This allows context switching to occur primarily in user mode, and can rely on kernel threads to directly invoke the functionality of the system kernel.
State switching of threads
Java multithreading mainly involves two kinds of data access synchronization, one is multi-threaded visible instance variable in the heap, one is the class member variable in method area, and the data in method call stack is thread-private, it does not need synchronization coordination. After the thread object calls the Start method, it enters the ready state to wait for the thread scheduler to allocate CPU resources into running, and then because of three reasons the thread may enter the waiting/blocked state: Call the Sleep/wait/suspend/join method, Called the blocking Io method, waiting for the lock to be acquired.
Java programming Interface for threads
The JDK's own development package supports the implementation of two threads, extends thread and implements Runnable, both of which implement threading by overriding the Run () method, the only difference being that the former restricts the current class from inheriting the parent class on another business.
1 Public classApp1extendsThread {2 @Override3 Public voidrun () {4 Super. Run ();5System.out.println (Thread.CurrentThread (). GetName () + ": Start");6 }7 8 Public Static voidMain (string[] args) {9APP1 thread =NewApp1 ();TenThread.setname ("App1 Thread"); One Thread.Start (); ASystem.out.println (Thread.CurrentThread (). GetName () + ": Start"); - } - } the - Public classApp1ImplementsRunnable { - @Override - Public voidrun () { +System.out.println (Thread.CurrentThread (). GetName () + ": Start"); - } + A Public Static voidMain (string[] args) { atThread App1thread =NewThread (NewApp1 ()); -App1thread.setname ("App1 Thread"); - App1thread.start (); -System.out.println (Thread.CurrentThread (). GetName () + ": Start"); - } -}
How threads are started:
#1 call Thread.Start () is an asynchronous implementation that indicates that the thread that the thread planner specifies is ready to allocate CPU resources and invoke the overridden run () method, so the execution of the thread is nondeterministic;
#2 call Thread.run () is a synchronous implementation and will not fetch any thread-related attributes, but rather a simple method call.
How the thread exits:
#1 thread.run () the thread exits gracefully after the execution ends.
#2 forced exit using Thread.stop () (not recommended)
#3 use Thread.Interrupt () to send a signal to the thread that needs to end, but not immediately stop the thread, the thread code needs to call thread.interrupted () (or a custom flag bit) to determine whether the current thread needs to end, This allows you to manually control the execution state of the thread.
Priority of the thread
With the Thread.setpriority (val) method, you can set the thread priority, ranging from 1 to 10, the thread scheduler tries to assign CPU resources to high-priority threads, but does not mean that high-priority threads always get CPU resources first; A child thread has the same priority as the parent thread.
The generation and avoidance of deadlocks
Thread.Suspend () and object.wait (), which do not specify a time-out period, are most likely to cause deadlocks. The tool JPS from the JDK can be used to monitor whether a thread has entered the deadlock state ($ jps-l PID).
Java (1): Multithreaded memory model and state switching