Types of Linux locks: 1. mutex (mutex lock), used to ensure that only one thread can access the object at any time; 2. rwlock (read-write lock), divided into read locks and write lock, which are suitable for situations where the frequency of reading data is much greater than the frequency of writing data; 3. spinlock (spin lock), only one thread can access the object at any time; 4. seqlock (sequential lock), It is used in situations where reading and writing can be distinguished, and there are many reading operations and few writing operations. The priority of writing operations is greater than that of reading operations.
#The operating environment of this tutorial: linux7.3 system, Dell G3 computer.
Mutex lock: mutex
Mutex lock: mutex, used to ensure At any time, only one thread can access the object. When the lock acquisition operation fails, the thread will go to sleep and be awakened when waiting for the lock to be released.
Read-write lock: rwlock
Read-write lock: rwlock, which is divided into read lock and write lock. When in read operation, multiple threads can be allowed to obtain read operations at the same time. But only one thread can obtain the write lock at the same time. Other threads that fail to acquire the write lock will go to sleep until they are awakened when the write lock is released.
Note: Write locks will block other read and write locks. When a thread acquires a write lock and is writing, the read lock cannot be acquired by other threads; writers have priority over readers (once there is a writer, subsequent readers must wait, and writers are given priority when waking up).
Spin lock: spinlock
Spin lock: spinlock, only one thread can access the object at any time. But when the lock acquisition operation fails, it will not go to sleep, but will spin in place until the lock is released. This saves the consumption of threads from sleep state to waking up, which will greatly improve efficiency in environments with short locking time. But if the locking time is too long, it will waste a lot of CPU resources.
RCU
RCU: Read-copy-update. When modifying data, you first need to read the data, then generate a copy, and modify the copy. After the modification is completed, update the old data to new data.
When using RCU, readers require almost no synchronization overhead. They neither need to obtain locks nor use atomic instructions, which will not cause lock competition, so there is no need to consider deadlock issues. The writer's synchronization overhead is relatively large. It needs to copy the modified data and must use a lock mechanism to synchronize and parallelize the modification operations of other writers. It is very efficient when there are a large number of read operations and a small number of write operations.
Semaphore: semaphore
The semaphore of the Linux kernel is the same in concept and principle as the IPC mechanism semaphore of the user mode SystemV, but It can never be used outside the kernel, so it has nothing to do with SystemV's IPC mechanism semaphore.
The semaphore needs to set an initial value when it is created, which means that several tasks can access the shared resources protected by the semaphore at the same time. An initial value of 1 becomes a mutex (Mutex), that is, at the same time Only one task can access the shared resource protected by the semaphore. If a task wants to access a shared resource, it must first obtain a semaphore. The operation of obtaining the semaphore will reduce the value of the semaphore by 1. If the current value of the semaphore is a negative number, it indicates that the semaphore cannot be obtained and the task must be suspended at that time. The waiting queue of the semaphore waits for the semaphore to be available; if the current value of the semaphore is a non-negative number, it means that the semaphore can be obtained, so the shared resources protected by the semaphore can be accessed immediately. After the task completes accessing the shared resource protected by the semaphore, it must release the semaphore. The release of the semaphore is achieved by adding 1 to the value of the semaphore. If the value of the semaphore is a non-positive number, it indicates that there is a task waiting for the current semaphore, so It also wakes up all tasks waiting on the semaphore.
rw_semaphore (read and write semaphore)
Read and write semaphores subdivide visitors, either readers or writers. Readers can only read and access the shared resources protected by the read and write semaphore while maintaining the read and write semaphore. If a In addition to reading, a task may also need to write, so it must be classified as a writer. It must obtain writer status before accessing shared resources. Writers can downgrade to readers if they find that they do not need write access. . There is no limit to the number of readers that a read-write semaphore can have at the same time, which means that any number of readers can own a read-write semaphore at the same time. If a read-write semaphore is not currently owned by a writer and no writer is waiting for a reader to release the semaphore, then any reader can successfully acquire the read-write semaphore; otherwise, the reader must be suspended until the writer releases the semaphore. . If a read-write semaphore is not currently owned by a reader or writer and there are no writers waiting for the semaphore, then a writer can successfully acquire the read-write semaphore, otherwise the writer will be suspended until there are no more visitors. . Therefore, the writer is exclusive and exclusive.
There are two implementations of read and write semaphores. One is universal and does not depend on the hardware architecture. Therefore, adding a new architecture does not require re-implementing it. However, the disadvantage is low performance and the difficulty of obtaining and releasing read and write semaphores. The overhead is high; the other is architecture-related, so the performance is high and the overhead of acquiring and releasing read and write semaphores is small, but adding a new architecture requires re-implementation. During kernel configuration, you can use options to control which implementation is used.
Read and write semaphore: rw_semaphore
The read and write semaphore subdivides the visitors, either for readers or writers. Readers maintain reading and writing During the semaphore period, only the shared resources protected by the read-write semaphore can be read and accessed. If a task needs to write in addition to reading, then it must be classified as a writer, and it must first access the shared resources before accessing the shared resources. Gain writer status, and writers can downgrade to readers if they find they no longer need write access. There is no limit to the number of readers that a read-write semaphore can have at the same time, which means that any number of readers can own a read-write semaphore at the same time. If a read-write semaphore is not currently owned by a writer and no writer is waiting for a reader to release the semaphore, then any reader can successfully acquire the read-write semaphore; otherwise, the reader must be suspended until the writer releases the semaphore. . If a read-write semaphore is not currently owned by a reader or writer and there are no writers waiting for the semaphore, then a writer can successfully acquire the read-write semaphore, otherwise the writer will be suspended until there are no more visitors. . Therefore, the writer is exclusive and exclusive.
There are two implementations of read and write semaphores. One is universal and does not depend on the hardware architecture. Therefore, adding a new architecture does not require re-implementing it, but the disadvantage is low performance, acquisition and release of read and write The overhead of semaphores is high; the other is architecture-related, so the performance is high, and the overhead of acquiring and releasing read and write semaphores is small, but adding a new architecture requires re-implementation. During kernel configuration, you can use options to control which implementation is used.
seqlock**** (sequential lock)
is used in situations where reading and writing can be distinguished, and there are many reading operations and few writing operations. has priority over read operations. The implementation idea of seqlock is to use an increasing integer to represent the sequence. When the write operation enters the critical section, the sequence is; when exiting the critical section, the sequence is again.
Write operations also need to obtain a lock (such as mutex). This lock is only used for write-write mutex to ensure that there is at most one ongoing write operation at the same time. When the sequence is an odd number, it means that a write operation is in progress. At this time, the read operation needs to wait until the sequence becomes an even number to enter the critical section. When a read operation enters the critical section, it is necessary to record the value of the current sequence. When it exits the critical section, compare the recorded sequence with the current sequence. If they are not equal, it means that a write operation occurred while the read operation entered the critical section. At this time, the read operation The operation read is invalid and needs to return and try again.
Seqlock writing must be mutually exclusive. However, the application scenario of seqlock itself is a situation where there is more reading and less writing, and the probability of write conflict is very low. So there is basically no performance loss in the write-write mutex here. The read and write operations do not need to be mutually exclusive. The application scenario of seqlock is that write operations take precedence over read operations. For write operations, there is almost no blocking (unless a small probability event such as a write-write conflict occurs), and only the additional action of sequence is required. The read operation does not need to be blocked, but retry is required when a read-write conflict is found. A typical application of seqlock is the update of the clock. There will be a clock interrupt every 1 millisecond in the system, and the corresponding interrupt handler will update the clock (write operation).
The user program can call system calls such as gettimeofday to obtain the current time (read operation). In this case, using seqlock can prevent too many gettimeofday system calls from blocking the interrupt handler (this would be the case if read-write locks are used instead of seqlock). The interrupt handler always takes priority, and if the gettimeofday system call conflicts with it, it doesn't matter if the user program waits.
1) Read-write locks distinguish between readers and writers, while mutex locks do not distinguish
2) Mutex locks can only One thread is allowed to access the object, regardless of reading or writing; the read-write lock only allows one writer at the same time, but allows multiple readers to read the object at the same time.
Related recommendations: "Linux Video Tutorial"
The above is the detailed content of What types of linux locks are there?. For more information, please follow other related articles on the PHP Chinese website!