Static synchronized methods in Java

Static synchronized methods in Java

Introduction

There are static synchronized methods in Java, that is, the synchronized keyword is used on static methods. Its lock is the Class object of the current class, that is to say, each class has only one Class object. Under multi-threading, this method can ensure that only one thread enters the static synchronization method to execute code at the same time, thereby avoiding Data errors and exceptions caused by concurrency.

Specifically, when a thread calls a static synchronization method M modified by synchronized, the JVM will try to acquire the lock of the Class object of this class. If the lock is not held by other threads, the current thread can acquire the lock and execute the code in the M method; otherwise, the current thread will block and wait for other threads to release the lock.

Here is a simple example:

public class Singleton{
    
    
    
    // 静态变量instance
    private static Singleton instance;
    
    // 私有构造方法
    private Singleton() {
    
    }
    
    // 静态同步方法getInstance
    public synchronized static Singleton getInstance() {
    
    
        if (instance == null) {
    
    
            instance = new Singleton();
        }
        return instance;
    }
    
    // 其他方法
    public void doSomething() {
    
    
        // ...
    }
}

In the above code, we define a Singleton class, and use the static variable instance and the static synchronization method getInstance to implement the singleton mode. For getInstance, we added the synchronized keyword to ensure thread-safe creation of Singleton instances. The other method doSomething has nothing to do with this.

It should be noted that in the static synchronization method, we cannot use the this keyword to acquire the lock, but should use the Class object of the current class, namely Singleton.class. Because in Java, each class corresponds to a unique Class object, so doing so can avoid unnecessary ambiguity and unexpected situations.

the case

Here is a simple example of a static synchronized method:

public class Counter {
    
    
    
    private static int count = 0;
    
    // 增加count计数器并打印计数日志
    public static synchronized void increment() {
    
    
        count++;
        System.out.println("Count is now " + count);
    }
    
    // 获取计数器
    public static int getCount() {
    
    
        return count;
    }
}

In the above example, we defined a Counter class and added a static variable count, a static synchronous method increment and a static method getCount. In the increment method, we use the synchronized keyword to ensure that the thread-safe self-increment counter is used, and the count log is output on the console. In the getCount method, we only need to return the value of the counter, so there is no need to use the synchronized keyword.

When calling a static synchronization method, if multiple threads try to access the method at the same time, the Class object of the class will be locked to avoid competition conflicts, ensuring that only one thread can execute the code block of this method at the same time. This ensures thread safety and avoids data errors and exceptions caused by synchronization issues.

Sorry, my last answer was wrong. Because the lock will be held until the execution of the increment method ends, other threads need to wait for the lock to be released before continuing to execute. Therefore, the actual result is sequential, and each thread executes the increment method in turn, and prints out the corresponding counter value.

Here is the updated sample code and output:

public class Main {
    
    
    
    public static void main(String[] args) {
    
    
        for (int i = 0; i < 10; i++) {
    
    
            Thread thread = new CounterThread();
            thread.start();
        }
    }
    
    private static class CounterThread extends Thread {
    
    
        
        @Override
        public void run() {
    
    
            // 执行10次自增操作
            for (int i = 0; i < 10; i++) {
    
    
                Counter.increment();
            }
        }
    }
}

public class Counter {
    
    
    
    private static int count = 0;
    
    // 增加count计数器并打印计数日志
    public static synchronized void increment() {
    
    
        count++;
        System.out.println("Count is now " + count);
    }
    
    // 获取计数器
    public static int getCount() {
    
    
        return count;
    }
}

The running results are as follows:

Count is now 1
Count is now 2
Count is now 3
Count is now 4
Count is now 5
Count is now 6
Count is now 7
Count is now 8
Count is now 9
Count is now 10
Count is now 11
Count is now 12
Count is now 13
Count is now 14
Count is now 15
Count is now 16
Count is now 17
Count is now 18
Count is now 19
Count is now 20
...

It can be seen that each thread executes the increment method in turn and prints out the corresponding counter value. It can be seen that using the static synchronization method can indeed ensure thread safety in a multi-threaded environment and avoid data errors and exceptions caused by race conditions.

  • Answer the question: Can the results be sequential using static synchronization methods?
  • Answer:
    Using a static synchronized method does guarantee thread safety when multiple threads access the method, but it does not mean that it guarantees sequential results.

In the above example, each thread will execute the increment method 10 times and print out the updated counter value. Since each call to the increment method needs to acquire a lock to ensure thread safety, only one thread among multiple threads can perform the self-increment operation of the counter at the same time, and other threads need to wait until the lock is acquired before continuing to execute. Therefore, the final output results will be printed out one by one in the order of entering and exiting the queue, rather than random random order.

However, if there are not only static methods, but also other processing logic is added to the program, such as IO operations such as reading and writing files, it may even cause the sequence of statement execution and code writing sequence to not necessarily correspond to the sequence of output results. order.

To sum up, using the static synchronization method can only ensure that multiple threads access the static method at the same time and execute the code blocks in it exclusively, but cannot guarantee the order of the output results.

Guess you like

Origin blog.csdn.net/qq_51447496/article/details/131057279