What does synchronized lock as a pessimistic lock?

What difference does synchronized make?

The previous two articles have covered the basics of “synchronized” and the contents of the lock (instance objects and Class objects). Today’s article would like to introduce an alternative, “synchronized code block,” which implements a more granular approach to synchronization. Let’s find out.

First to introduce how to write synchronous code block, the general code framework is like this:

synchronized(xxx) {

    

}

Copy the code

XXX can be this or Object or xxx.class, and we will discuss the three different locking methods.

this

Lock the current object in the same way that you used the synchronous instance.

public class SynchronizedCodeTest {



    public static void main(String[] args) {

        SynchronizedCodeTest synchronizedCodeTest = new SynchronizedCodeTest();

        for (int i = 0; i < 5; i ++) {

            Thread thread = new Thread(() -> {

                synchronizedCodeTest.testSynchronizedCode();

            });

            thread.start();

        }

    }



    int count = 0;

    public void testSynchronizedCode(a) {

        System.out.printf("%s-testSynchronizedCode-start-count=%s\n", Thread.currentThread().getName(), count);

        synchronized (this) {

            System.out.printf("%s-testSynchronizedCode-synchronized-start-count=%s\n", Thread.currentThread().getName(), count);

            count ++;

            System.out.printf("%s-testSynchronizedCode-synchronized-end-count=%s\n", Thread.currentThread().getName(), count);

        }

        System.out.printf("%s-testSynchronizedCode-end-count=%s\n", Thread.currentThread().getName(), count);

    }



}

Copy the code

Running results:


We focus on this part of the red box and blue box as a result, the red box is a synchronized block of code inside, between threads are mutually exclusive, but in the blue box “Thread – 0”, in the process of performing synchronized block other threads not synchronized block or in the execution, it illustrates the granularity of locking becomes into a method inside the synchronized block of code between incompatible, Unsynchronized block code is not mutually exclusive, and the final value of count is 5, indicating that only one thread is executing at a time until the synchronized block is executed.

Let’s write another test and see what synchronized(this) does.

public class SynchronizedCodeTest {



    public static void main(String[] args) {

        for (int i = 0; i < 5; i ++) {

            SynchronizedCodeTest synchronizedCodeTest = new SynchronizedCodeTest();

            Thread thread = new Thread(() -> {

                synchronizedCodeTest.testSynchronizedCode();

            });

            thread.start();

        }

    }

}

Copy the code

Running results:


Synchronized (this) locks the current object, and if count is 1, synchronized(this) locks the current object. Public synchronized void testSynchronizedMethod()

Object

The synchronization block gives you the flexibility to lock anything we create instead of just the current object, as we’ll see below.



public class SynchronizedCodeTest {



    public static void main(String[] args) {

        Object lock = new Object();

        SynchronizedCodeTest synchronizedCodeTest = new SynchronizedCodeTest(lock);

        for (int i = 0; i < 5; i ++) {

            Thread thread = new Thread(() -> {

                synchronizedCodeTest.testSynchroniedLock();

            });

            thread.start();

        }

    }



    int count = 0;



    Object lock = null;

    public SynchronizedCodeTest(Object lock) {

        this.lock = lock;

    }



    public void testSynchroniedLock(a) {

        System.out.printf("%s-testSynchroniedLock-start-count=%s\n", Thread.currentThread().getName(), count);

        synchronized (lock) {

            System.out.printf("%s-testSynchroniedLock-synchronized-start-count=%s\n", Thread.currentThread().getName(), count);

            count ++;

            System.out.printf("%s-testSynchroniedLock-synchronized-end-count=%s\n", Thread.currentThread().getName(), count);

        }

        System.out.printf("%s-testSynchroniedLock-end-count=%s\n", Thread.currentThread().getName(), count);

    }



}



Copy the code

Running results:


In this code, we create a lock object, which is passed as a parameter to the synchronizedCodeTest object. We see that the result is that the five threads are executing sequentially in the synchronized block code, and the count is finally 5. This code does not see the flexibility of the lock object. Here is an example that changes the test code slightly so that each thread has its own synchronizedCodeTest object.

public static void main(String[] args) {

 Object lock = new Object();

 for (int i = 0; i < 5; i ++) {

 SynchronizedCodeTest synchronizedCodeTest = new SynchronizedCodeTest(lock);

  Thread thread = new Thread(() -> {

   synchronizedCodeTest.testSynchroniedLock();

  });

  thread.start();

 }

}

Copy the code

Running results:


It turns out that even though we create a synchronizedCodeTest object for each thread, the synchronized code blocks for the five threads are executed serially no matter how they run because we only create a single lock object. The lock object for all five SynchronizedCode Tests is the same, and therefore the competing resource is the same. In the previous article, we needed to use the “static synchronization method” to execute multiple instances synchronously. Now we don’t need to use the synchronized code block, which only needs to lock the same instance object.

In addition, the result of this example is that count ends up being 1 for each instance. This is because each synchronizedCodeTest object has its own independent variable count, so threads do not affect each other.

xxx.class

Public static synchronized testSynchronizedStatic(); public synchronized testSynchronizedStatic(); Let’s go straight to the code example.

public class SynchronizedCodeTest {



    public static void main(String[] args) {

        for (int i = 0; i < 5; i ++) {

            SynchronizedCodeTest synchronizedCodeTest = new SynchronizedCodeTest();

            Thread thread = new Thread(() -> {

                synchronizedCodeTest.testSynchronizedCodeClass();

            });

            thread.start();

        }

    }



    int count = 0;

    public void testSynchronizedCodeClass(a) {

        System.out.printf("%s-testSynchronizedCodeClass-start-count=%s\n", Thread.currentThread().getName(), count);

        synchronized (SynchronizedCodeTest.class) {

            System.out.printf("%s-testSynchronizedCodeClass-synchronized-start-count=%s\n", Thread.currentThread().getName(), count);

            count ++;

            System.out.printf("%s-testSynchronizedCodeClass-synchronized-end-count=%s\n", Thread.currentThread().getName(), count);

        }

        System.out.printf("%s-testSynchronizedCodeClass-end-count=%s\n", Thread.currentThread().getName(), count);

    }



}

Copy the code

Running results:


Each thread has its own instance, but locking the Class causes the synchronized blocks of each thread instance Object to be executed serially, which is the same as locking multiple instances of the same Object. I personally prefer to lock an Object rather than a Class Object.

conclusion

This article introduces the three ways synchronizd blocks can be used, and details the differences between them. Simply make a list.

type use Range of action
this synchronized(this){} Locks the current instance object
object synchronized(lock){} Lock other instance objects, more flexible
xxx.class synchronized(xxx.class){} Lock the Class object

A total of 3 articles to introduce you to the specific usage of synchronized, mainly because before some articles suddenly into the Java source code and JVM source code, let many friends feel a little difficult, and even friends do not come to see the title, so this time to introduce some relatively simple usage, Let us first understand, behind a few more in-depth synchronized original rational article, I hope you can also see, there will be a very big harvest.

Original is not easy, we help forward, point to see.

What does synchronized lock as a pessimistic lock?

What difference does synchronized make?

Take a look at Java daemon threads from the JVM’s perspective

After years of writing Java code, finally debug into the JVM

The latest and simplest openJDK13 code compilation

Understand the Java thread priority, but also the corresponding operating system priority, otherwise you will step on the pit

The most basic knowledge of threads

The boss told you to stop blocking

You can eat fast food and learn serial, parallel, and concurrency

Make a cup of tea and learn asynchrony

How much do we know about the process?

Design patterns seen and forgotten, forgotten and read?

If you reply “Design Mode”, you can get the ebook “One Story one Design Mode”

Think the article is useful to help forward & praise, thank you friends!

LieBrother

This article is formatted using MDNICE