What is a process

A process is an application (App) that is running in the system. Each process is independent of each other, each process runs in its own dedicated and protected memory space; The activity monitor allows you to view the processes that are started on your Mac system.

What is a thread

Thread is the basic execution unit of a process. All tasks of a process are executed in thread. The process must have at least one thread if it wants to perform a task. The program starts with a thread by default. This thread is called the main thread or UI thread.

The relationship between processes and threads

Address space: Threads of the same process share the address space of the same process, but the address space between processes is independent. Resource ownership: Threads in the same process share the resources of the process, such as memory, I/O, and CPU, but the resources between the processes are independent.

  1. When a process crashes, it has no effect on other processes in protected mode, but when a thread crashes, the entire process dies. So multiple processes are more robust than multiple threads.
  2. The process switchover consumes a large number of resources and is highly efficient. So when it comes to frequent switching, threads are better than processes. Similarly, if concurrent operations are required simultaneously and share some variables, only threads can be used, not processes
  3. Execution process: Each independent process has a program running entry, sequential execution sequence and program entry. However, threads cannot be executed independently, and must be dependent on the application program, which provides multiple thread execution control.
  4. Threads are the basic unit of processor scheduling, but processes are not.
  5. Threads have no address space; they are contained in the process address space
  6. ThreadLocalStorage (TLS). Thread-local storage is a separate private space provided by some operating systems for threads, but it usually has a very limited capacity. Sync_data/is used to acquire a synchronization lockobjc_initIt also exists in functions.)

The meaning of multithreading

Multithreading is not really concurrent in principle, it’s just the CPU switching between tasks directly and quickly, and this interval is called time slices. True concurrency is built on a multi-core basis

Advantages:

  1. Can properly improve the efficiency of the implementation of procedures
  2. Appropriate resource utilization (CPU memory)
  3. When the tasks on the thread finish executing, the thread is automatically destroyed

Disadvantages:

  1. Starting threads requires a certain amount of memory (512KB per thread by default)
  2. If a large number of threads are enabled, a large amount of memory space will be occupied and the performance of the program will be degraded
  3. The more threads there are, the greater the CPU overhead on the calling thread
  4. More complex programming such as communication between threads, multi-threaded data sharing

One core at a time, the CPU can only process one thread, in other words, only one thread at a time executing multithreading is actually the CPU fast switching between multiple threads; The CPU threads are scheduled fast enough to create the illusion that multiple threads are executing simultaneously. If the number of threads is very large, the CPU will switch between N threads, which consumes a lot of CPU resources. The number of times each thread is scheduled will be reduced, and the execution efficiency of the thread will be reduced.

Several options for multithreading

Thread life cycle

Thread scheduling policy

Saturated strategy

  1. AbortPolicy directly thrown RejectedExecutionExeception exceptions to prevent normal operation of system
  2. CallerRunsPolicy rolls back the task to the caller
  3. DisOldestPolicy drops the task that is waiting the longest
  4. DisCardPolicy Discards the task directly

The influencing factors of task execution speed

  1. cpu
  2. Priority of tasks
  3. Task complexity
  4. Current status of the thread

Priority reversal

  1. IO intensive: Frequent waiting
  2. CPU intensive: rarely waits

To avoid starvation, CPU scheduling IO intensive increases the priority

Factors that change thread priority

  1. The user specifies the priority
  2. Depending on the frequency of the wait
  3. Tasks that are not performed for long periods of time also increase their priority

Spin locks and mutexes

  • The mutex detects that other threads performing the current thread sleep (ready state) have been waiting for the wake execution to turn on
  • Spin-locks that detect other threads executing the current thread query – busy, etc., are high performance and are commonly used for short tasks

Atomic: the default property for multithreaded development! Adding a lock (spin-lock) to the setter method of a property ensures that only one thread is writing to the property at a time. But more than one thread at a time can be nonatomic. There is no lock! High performance!

See the source code:

void objc_setProperty(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic, signed char shouldCopy) 
{
    bool copy= (shouldCopy && shouldCopy ! = MUTABLE_COPY);bool mutableCopy = (shouldCopy == MUTABLE_COPY);
    reallySetProperty(self, _cmd, newValue, offset, atomic, copy, mutableCopy);
}

Copy the code
static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy.bool mutableCopy)
{
  	 //....
    if(! atomic) { oldValue = *slot; *slot = newValue; }else{ spinlock_t& slotlock = PropertyLocks[slot]; slotlock.lock(); oldValue = *slot; *slot = newValue; slotlock.unlock(); }}Copy the code

From above we can see that atomic is not a lock, but a lock symbol.

Threads andRunloop

  1. A runloop corresponds to a core thread. The reason why it is called a core thread is that runloops can be nested, but there can only be one core thread. Their relationship is stored in a global dictionary.
  2. The runloop manages the thread. When the runloop is enabled, the thread will go to sleep after executing a task, and it will wake up to execute the task.
  3. The runloop is created when it is first fetched and destroyed when the thread ends.
  4. For the main thread, the runloop is created by default as soon as the program starts.
  5. For the child thread, the runloop is lazily loaded and created only when we use it, so be careful when using a timer for the child thread: make sure the runloop is created for the child thread, otherwise the timer will not call back.

supplement

__bridge only casts, but does not modify object (memory) management rights; __bridge_retained (oc) converts the oc object to CoreFoundation, but lets you use CFRealeas or other methods to release the object. __bridge_transfer converts the oc object to CoreFoundation. And return the memory management permission to ARC