This is the 17th day of my participation in Gwen Challenge

What is a thread lock?

In concurrent programming, it is common to encounter multiple threads accessing the same shared resource. At this time, developers must consider how to maintain data consistency. Synchronized keyword is often used to maintain data consistency in Java. The synchronized mechanism locks shared resources, and only the thread that obtains the lock can access the shared resources. In this way, the access to the shared resources is forced to be sequential.

After the introduction of multi-threading, the concept of lock was introduced to solve the problem of thread safety. In Java, synchronized and lock are commonly used.

In Java lock

Each Java object can be used as a lock to achieve synchronization. Although everything in Java is an object, the lock must be a reference type, not a basic data type. Each object of a reference type can implicitly act as a lock for synchronization, which is automatically acquired by the executing thread before it enters a synchronized block. The lock is automatically released when the thread cedes control of the synchronized block, either through a normal statement exit or an exception thrown during execution. The only way to obtain a lock is to access the synchronized block or method protected by the internal lock.

Through the synchronized keyword to achieve thread synchronization lock

==synchronized locks objects ==

Three application modes of Synchronized:

1. For instance methods (common methods), the current instance is locked, and the lock of the current instance must be obtained before entering the synchronization code; Such as:

public class SyncTest implements Runnable{
// Share resource variables
static int count = 0;

    @Override
    public synchronized void run() {
        increaseCount();
    }

    private synchronized  void increaseCount() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + count++);
            try {
                Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }}}public static void main(String[] args) throws InterruptedException {
        SyncTest syncTest1 = new SyncTest();
// SyncTest syncTest2 = new SyncTest();
        Thread thread1 = new Thread(syncTest1, "thread1");
        Thread thread2 = new Thread(syncTest1, "thread2");
        thread1.start();
        thread2.start();
    }
    
    /** * result * thread1:0 * thread1:1 * thread1:2 * thread1:3 * thread1:4 * thread2:5 * thread2:6 * thread2:7 * thread2:8 *  thread2:9 */
}
Copy the code

Thread1 and Thread2 execute sequentially. When two different objects are created, the two threads execute synchronously, so == locks the object ==. As follows:

public class SyncTest implements Runnable{
// Share resource variables
static int count = 0;

    @Override
    public synchronized void run() {
        increaseCount();
    }

    private synchronized  void increaseCount() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + count++);
            try {
                Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }}}public static void main(String[] args) throws InterruptedException {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        Thread thread1 = new Thread(syncTest1, "thread1");
        Thread thread2 = new Thread(syncTest2, "thread2");
        thread1.start();
        thread2.start();
    }

    Thread2:1 thread1:0 thread1:2 thread2:3 thread2:4 thread1:4 thread1:5 thread2:5 thread2:6 thread1:7 */
}
Copy the code

2. Static method, the current class lock, into the synchronization code to obtain the current class object lock;

public class SyncTest implements Runnable {
    // Share resource variables
    static int count = 0;

    @Override
    public synchronized void run() {
        increaseCount();
    }

    private sys static void increaseCount() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + count++);
            try {
                Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }}}public static void main(String[] args) throws InterruptedException {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        Thread thread1 = new Thread(syncTest1, "thread1");
        Thread thread2 = new Thread(syncTest2, "thread2");
        thread1.start();
        thread2.start();
    }

    Thread1 :0 thread1:1 thread1:2 thread1:3 thread1:4 thread2:5 thread2:6 thread2:7 thread2:8 thread2:9 */
}
Copy the code

Synchronized locks static methods, such as creating two objects to separate the two threads and executing them sequentially.

3. On the code block, this needs to specify the object to lock, given the specified object to lock, before entering the synchronization code to obtain the specified object lock.

public class SyncTest implements Runnable {
    // Share resource variables
    static int count = 0;
    private byte[] mBytes = new byte[0];

    @Override
    public synchronized void run() {
        increaseCount();
    }

    private void increaseCount() {
        // Assume that code for other operations is omitted.
        / /..........................................
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + ":" + count++);
                try {
                    Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }}}}public static void main(String[] args) throws InterruptedException {
        SyncTest syncTest1 = new SyncTest();
        SyncTest syncTest2 = new SyncTest();
        Thread thread1 = new Thread(syncTest1, "thread1");
        Thread thread2 = new Thread(syncTest1, "thread2");
        thread1.start();
        thread2.start();
    }

    Thread1 :0 thread1:1 thread1:2 thread1:3 thread1:4 thread2:5 thread2:6 thread2:7 thread2:8 thread2:9 */
Copy the code

When only part of the code needs to be synchronized, synchronized acts on a code block, passing in an object as an argument, and has the same effect as a normal method, locking the object.