This is the third day of my participation in the August More text Challenge. For details, see: August More Text Challenge

Hear fair lock, non-fair lock, rechargeable lock, non-fair lock, shared lock, exclusive lock…. Are you confused by these nouns? Let’s classify and summarize several common lock concepts. I hope it can help you

Through the article you will mainly understand the Java referred to a variety of locks at the same time to understand the meaning and characteristics behind a variety of locks, this article mainly introduces the optimistic lock, pessimistic lock, fair lock and other content.

An overview of lock information

To begin our exploration, let’s take an overview of all the lock information in Java. According to the different characteristics of locks can be divided into different types as shown in the figure.

Optimistic lock, pessimistic lock after all is what ghost?

Optimistic locking

There is a fable about two thirsty men who find a glass half full. “Ah,” said one, “I have found water at last! Although the water is only half full now, but a journey of a thousand miles begins with a single step, with a good beginning, I am sure I can find more water. “So he became happy. And the other person thought, “How come the glass is only half full? What’s the use of half a glass of water?” In his anger he dropped his glass of water and then sat down thirsty.

The same is half a glass of water, in the optimistic people see hope, and pessimistic people see is hope. This inside refraction comes out actually is optimistic lock, pessimistic lock philosophy.

For optimistic locking, it believes that when multiple threads operate, there will be no interference from other threads, so when operating on shared resources, optimistic locking will not lock the resources, it allows other threads to operate at the same time.

In the face of multi-threaded simultaneous operation and data update, the general process is as follows:

  • When we update data, we will determine whether other threads have modified our data during the modification period. If no modification has been made, it means that only we are operating during this period. At this time, the data information is modified normally.

  • If the data is inconsistent when the data is modified, it indicates that someone has modified the data during this period. At this point, you will not continue to modify the update action, but will choose to abandon, error, retry and other policies.

    The most typical examples of optimistic locking are: Git, atom, etc.

    In mysql, a hidden field is added to the data table to determine whether the data has been modified in a certain time. Its work is the most typical manifestation of optimistic locking. When data is read, the version field information is kept alone, and each field changes once the data is updated. When submitting the data, determine whether the field information in the data table is the same as that read before. If the data is always updated, the update succeeds; if the data is different, the update fails.Copy the code

Pessimistic locking

Pessimistic locking is exactly the opposite of optimistic locking. In pessimistic locking, all operations have potential thread safety problems. Therefore, the strategy adopted by pessimistic locking is to lock the shared resource data first and then operate it later.

The most typical example of pessimistic locking is the synchronized keyword, which can be used to avoid the threading problems caused by a large number of concurrent threads.

Optimistic lock, pessimistic lock how to choose

Optimistic lock and pessimistic lock each have their own suitable scenarios, in general:

Pessimistic locking is more suitable for concurrent operations where there are more writes than reads, or where critical sections are held for a long time. Optimistic locking is more suitable for concurrent operations where there are more reads and fewer writes.

Fair? Is it unfair? What is fair!

Colloquially speaking, fair lock is equivalent to the queue in reality, first come, first served; Non-fair lock is considered to be disorderly, who grabbed who;

In Java’s locking mechanism, a lock is a fair lock if each thread group is guaranteed to have access to the lock. On the other hand, if every thread is not guaranteed to get the lock, that is, there are threads starving to death, then the lock is not fair. Threads are generally allowed to jump the queue if they are not fair.

Fair and unfair locks in JUC are determined by passing true or fasle to ReentrantLock.

Example code:

Let’s simulate a scenario where each thread needs to perform two printing tasks, each of which requires the lock information to be obtained.

// Print the task

class PrintQueue {
    // Print the lock information that was held when the task lock proceeded
    private Lock queueLock = new ReentrantLock(true);
    
    public void printJob(Object document) {
        // Make the first print
        queueLock.lock();
        try {
            int duration = new Random().nextInt(10) + 1;
            System.out.println(Thread.currentThread().getName() + "Printing in progress, need." + duration);
            Thread.sleep(duration * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            queueLock.unlock();
        }
        // Print the second time
        queueLock.lock();
        try {
            int duration = new Random().nextInt(10) + 1;
            System.out.println(Thread.currentThread().getName() + "Printing in progress, need." + duration+"Seconds");
            Thread.sleep(duration * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{ queueLock.unlock(); }}}// The task thread
class Job implements Runnable {

    PrintQueue printQueue;

    public Job(PrintQueue printQueue) {
        this.printQueue = printQueue;
    }

    @Override
    public void run(a) {
        System.out.println(Thread.currentThread().getName() + "Start printing.");
        printQueue.printJob(new Object());
        System.out.println(Thread.currentThread().getName() + "Print done."); }}Copy the code

/** * Description: Demonstrate fair situation */

public class FairLock {

    public static void main(String[] args) {
        PrintQueue printQueue = new PrintQueue();
        Thread thread[] = new Thread[10];
        for (int i = 0; i < 3; i++) {
            thread[i] = new Thread(new Job(printQueue));
        }
        for (int i = 0; i < 3; i++) {
            thread[i].start();
            try {
                Thread.sleep(100);
            } catch(InterruptedException e) { e.printStackTrace(); }}}}Copy the code
Code analysis: Multiple print task threads are started in the main thread, and each print task needs to be completed in the print thread. Each print task requires two prints. Result information for fair locking: Thread-0 is printing, needs 6 thread-1 is printing, needs 3 thread-2 is printing, needs 9 thread-0 is printing, It takes 2 seconds to complete the printing of thread-0 and 8 seconds to complete the printing of thread-1 and 3 seconds to complete the printing of thread-2. Conclusion: It is not difficult to find that the fair lock output information is completely in order to print, there is no phenomenon of queue jumping. If there is a queue-jumping phenomenon, then a thread should be able to enter the second print task when it has finished printing.Copy the code

Private Lock queueLock = new ReentrantLock(true); False: false: false: false

Output result information for non-cofair locking: Thread-0 is printing, needs 3 thread-1 is printing, needs 6 seconds thread-2 is printing, needs 6 seconds thread-0 is printing, needs 7 thread-1 is printing, needs 6 seconds thread-0 is printing, needs 7 thread-1 is printing, needs 7 thread-1 is printing, It takes 10 seconds for the printing of thread-1 to complete, and 6 for the printing of thread-2 to complete, and 10 seconds for the printing of thread-2 to completeCopy the code

In the case of non-fair locking, when the first print task of a thread is completed, it does not execute the print task in the order of the thread. Instead, the phenomenon of ‘queue jumping’ occurs — the second print task of the current thread is executed.

Fair locking ensures that threads have equal access to execution, but it reduces throughput and slows execution.

Non-fair locking can improve system throughput and efficiency. But random queue-jumping can lead to hunger.

summary

For the sake of the overall structure of the article, shared locks, exclusive locks, and reentrant locks will be covered in more detail in the next article. This time we mainly analyzed optimistic lock, pessimistic lock, fair lock, non-fair lock and other information. I hope it helps you.