Processes and threads are related to each other and very much similar, hence create confusion to understand the differences between both of them.
1.1 Process
What is Process ?
A process is an instance of a program that is being executed;
A process can create other processes to perform multiple tasks at a time;
Each process contains its own memory space and does not share it with the other processes.
Process States
NEW: A new process is being created.
READY: A process is ready and waiting to be allocated to a processor.
RUNNING: The program is being executed.
WAITING: Waiting for some event to happen or occur.
TERMINATED: Execution finished.
How it works ?
Firstly, the program is loaded into the computer’s memory in binary code after translation.
A program requires OS resources to run it. The resources such that registers, program counter, and a stack, and these resources are provided by the OS.
A register can have an instruction, a storage address, or other data that is required by the process.
The program counter maintains the track of the program sequence.
The stack has information on the active subroutines of a computer program.
Features of Process
Each time we create a process, we need to make a separate system call for each process to the OS. The fork() function creates the process.
Each process exists within its own address or memory space.
Each process is independent and treated as an isolated process by the OS.
Processes need IPC (Inter-process Communication) in order to communicate with each other.
A proper synchronization between processes is not required.
1.2 Thread
What is Thread?
A thread is the subset of a process and is also known as the lightweight process.
A process can have more than one thread, and these threads are managed independently by the scheduler.
Threads have some common information, such as data segment, code segment, files, etc., that is shared to their peer threads. But contains its own registers, stack, and counter.
How it works ?
When a process starts, OS assigns the memory and resources to it. Each thread within a process shares the memory and resources of that process only.
Threads are mainly used to improve the processing of an application.
If a single thread executes in a process, it is known as a single-threaded And if multiple threads execute simultaneously, then it is known as multi-threading.
Features of Thread
Threads share data, memory, resources, files, etc., with their peer threads within a process.
One system call is capable of creating more than one thread.
Each thread has its own stack and register.
Threads can directly communicate with each other as they share the same address space.
Threads need to be synchronized in order to avoid unexpected scenarios.
1.3 Differences
Key Differences
A process is independent and does not contained within another process, whereas all threads are logically contained within a process.
Processes are heavily weighted, whereas threads are light-weighted.
A process can exist individually as it contains its own memory and other resources, whereas a thread cannot have its individual existence.
A proper synchronization between processes is not required. In contrast, threads need to be synchronized in order to avoid unexpected scenarios.
Processes can communicate with each other using inter-process communication only; in contrast, threads can directly communicate with each other as they share the same address space.
Difference Table
Process
Thread
A process is an instance of a program that is being executed or processed.
Thread is a segment of a process or a lightweight process that is managed by the scheduler independently.
Processes are independent of each other and hence don’t share a memory or other resources.
Threads are interdependent and share memory.
Each process is treated as a new process by the operating system.
The operating system takes all the user-level threads as a single process.
If one process gets blocked by the operating system, then the other process can continue the execution.
If any user-level thread gets blocked, all of its peer threads also get blocked because OS takes all of them as a single process.
Context switching between two processes takes much time as they are heavy compared to thread.
Context switching between the threads is fast because they are very lightweight.
The data segment and code segment of each process are independent of the other.
Threads share data segment and code segment with their peer threads; hence are the same for other threads also.
The operating system takes more time to terminate a process.
Threads can be terminated in very little time.
New process creation is more time taking as each new process takes all the resources.
A thread needs less time for creation.
二、并发 vs 并行
2.1 Concurrency
Concurrency relates to an application that is processing more than one task at the same time. Concurrency is an approach that is used for decreasing the response time of the system by using the single processing unit.
Concurrency is creates the illusion of parallelism, however actually the chunks of a task aren’t parallelly processed, but inside the application, there are more than one task is being processed at a time. It doesn’t fully end one task before it begins ensuing.
Concurrency is achieved through the interleaving operation of processes on the central processing unit(CPU) or in other words by the context switching. that’s rationale it’s like parallel processing. It increases the amount of work finished at a time.
In the above figure, we can see that there is multiple tasks making progress at the same time. This figure shows the concurrency because concurrency is the technique that deals with the lot of things at a time.
2.2 Parallelism
Parallelism is related to an application where tasks are divided into smaller sub-tasks that are processed seemingly simultaneously or parallel. It is used to increase the throughput and computational speed of the system by using multiple processors. It enables single sequential CPUs to do lot of things “seemingly” simultaneously.
Parallelism leads to overlapping of central processing units and input-output tasks in one process with the central processing unit and input-output tasks of another process. Whereas in concurrency the speed is increased by overlapping the input-output activities of one process with CPU process of another process.
In the above figure, we can see that the tasks are divided into smaller sub-tasks that are processing simultaneously or parallel. This figure shows the parallelism, the technique that runs threads simultaneously.
2.3 Differences
Concurrency
Parallelism
Concurrency is the task of running and managing the multiple computations at the same time.
While parallelism is the task of running multiple computations simultaneously.
Concurrency is achieved through the interleaving operation of processes on the central processing unit(CPU) or in other words by the context switching.
While it is achieved by through multiple central processing units(CPUs).
Concurrency can be done by using a single processing unit.
While this can’t be done by using a single processing unit. it needs multiple processing units.
Concurrency increases the amount of work finished at a time.
While it improves the throughput and computational speed of the system.
Concurrency deals lot of things simultaneously.
While it do lot of things simultaneously.
Concurrency is the non-deterministic control flow approach.
While it is deterministic control flow approach.
In concurrency debugging is very hard.
While in this debugging is also hard but simple than concurrency.
三、线程的状态及转换
3.1 线程的状态
State
Description
NEW
A thread that has not yet started is in this state.
RUNNABLE
A thread executing in the Java virtual machine is in this state.
BLOCKED
A thread that is blocked waiting for a monitor lock is in this state.
WAITING
A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
TIMED_WAITING
A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
TERMINATED
A thread that has exited is in this state.
3.2 状态间转换
3.3 相关类的方法
Method
Description
Object.wait()
Causes the current thread to wait until it is awakened, typically by being notified or interrupted, and the lock will be released.
Thread.sleep()
Causes the currently executing thread to sleep (temporarily cease execution) and the lock will not be released.
Thread.yield()
A hint to the scheduler that the current thread is willing to yield its current use of a processor.
Thread.join()
Caller (main) thread will wait for this callee thread to die (run out).
Thread.interrupt()
Instead of terminating the thread, it sends an interrupt notification to the thread so that it can decide to responde to the interrupt notification at an appropriate time (the response can be to terminate the thread or not to respond).
Thread.stop()
Deprecated
Thread.suspend()
Deprecated
Thread.resume()
Deprecated
四、内置锁
4.1 锁的谁?
// Fruit fruit = new Fruit();publicclassFruit{privatefinalString lock ="I am a lock";// locked 'fruit' instancepublicsynchronizedvoidsprout(){System.out.println("i am sprouting");}// locked 'fruit' instancepublicvoidgrow(){synchronized(this){System.out.println("i am growing");}}// locked 'lock' instancepublicvoidgrew(){synchronized(lock){System.out.println("i have been grown");}}// locked 'Fruit.class'publicvoidbloom(){synchronized(Fruit.class){System.out.println("i am blooming");}}// locked 'Fruit.class'publicsynchronizedstaticvoidbearFruit(){System.out.println("i am bearing fruit");}}
These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable.
ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
5.2 实例
代码
packagecom.simwor.simpletest;importjava.util.concurrent.atomic.AtomicInteger;publicclassThreadLocalTest{publicstaticvoidmain(String[] args){newThreadLocalTest().run();}/**
* 3. Mock modifying data in parallel
*/privatevoidrun(){Number no =newNumber();for(int i =0; i <3; i++)newThread(newRunner(no)).start();}/**
* 2. Mock modifying data
*/privateclassRunnerimplementsRunnable{privateNumber no;publicRunner(Number no){this.no = no;}@Overridepublicvoidrun(){for(int i =0; i <10000; i++)
no.increment();// print result after invokingSystem.out.println(no);
no.destroy();}}/**
* 1. Mock different ways of keeping data
*/privateclassNumber{privateint publicNo;privateAtomicInteger atomicNo =newAtomicInteger(0);privateThreadLocal<Integer> localNo =ThreadLocal.withInitial(()->0);publicvoidincrement(){
publicNo++;
atomicNo.incrementAndGet();
localNo.set(localNo.get()+1);}publicvoiddestroy(){
localNo.remove();}@OverridepublicStringtoString(){return"Number{"+"publicNo="+ publicNo +", atomicNo="+ atomicNo.get()+", localNo="+ localNo.get()+'}';}}}
/**
* ThreadLocalMap is a customized hash map suitable only for
* maintaining thread local values. No operations are exported
* outside of the ThreadLocal class. The class is package private to
* allow declaration of fields in class Thread. To help deal with
* very large and long-lived usages, the hash table entries use
* WeakReferences for keys. However, since reference queues are not
* used, stale entries are guaranteed to be removed only when
* the table starts running out of space.
*/staticclassThreadLocalMap{privateThreadLocal.ThreadLocalMap.Entry[] table;/**
* Construct a new map initially containing (firstKey, firstValue).
* ThreadLocalMaps are constructed lazily, so we only create
* one when we have at least one entry to put in it.
*/ThreadLocalMap(ThreadLocal<?> firstKey,Object firstValue){
table =newThreadLocal.ThreadLocalMap.Entry[INITIAL_CAPACITY];int i = firstKey.threadLocalHashCode &(INITIAL_CAPACITY -1);
table[i]=newThreadLocal.ThreadLocalMap.Entry(firstKey, firstValue);
size =1;setThreshold(INITIAL_CAPACITY);}}
ThreadLocal.set() 方法,修改的 map 变量是栈封闭的;
/**
* Sets the current thread's copy of this thread-local variable
* to the specified value. Most subclasses will have no need to
* override this method, relying solely on the {@link #initialValue}
* method to set the values of thread-locals.
*
* @param value the value to be stored in the current thread's copy of
* this thread-local.
*/publicvoidset(T value){Thread t =Thread.currentThread();ThreadLocalMap map =getMap(t);if(map !=null){
map.set(this, value);}else{createMap(t, value);}}
ThreadLocal.get() 方法,查看的 map 变量是栈封闭的;
/**
* Returns the value in the current thread's copy of this
* thread-local variable. If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
*
* @return the current thread's value of this thread-local
*/publicTget(){Thread t =Thread.currentThread();ThreadLocalMap map =getMap(t);if(map !=null){ThreadLocalMap.Entry e = map.getEntry(this);if(e !=null){@SuppressWarnings("unchecked")T result =(T)e.value;return result;}}returnsetInitialValue();}
5.4 内存泄露问题
staticclassThreadLocalMap{staticclassEntryextendsWeakReference<ThreadLocal<?>>{Object value;Entry(ThreadLocal<?> k,Object v){super(k);
value = v;}}...}