JavaRush/Java Blog/Random EN/Thread synchronization. Java synchronized statement

Thread synchronization. Java synchronized statement

Published in the Random EN group
members
Hello! Today we will continue to consider the features of multi-threaded programming and talk about thread synchronization.
Thread synchronization.  synchronized statement - 1
What is "synchronization"? Outside of programming, this refers to some setting that allows two devices or programs to work together. For example, a smartphone and a computer can be synchronized with a Google account, a personal account on a website can be synchronized with accounts on social networks in order to log in using them. Synchronization of threads has a similar meaning: it is a setting for the interaction of threads with each other. In the previous lectures, our streams lived and worked separately from each other. One was counting something, the second was sleeping, the third was outputting something to the console, but they did not interact with each other. In real programs, such situations are rare. Several threads can actively work, for example, with the same data set and change something in it. This creates problems. Imagine that multiple threads write text to the same location, such as a text file or console. This file or console in this case becomes a shared resource. The threads do not know about each other's existence, so they simply write down everything they can do in the time that the thread scheduler allocates to them. In a recent lecture of the course, we had an example of what this would lead to, let's remember it: Thread synchronization.  synchronized-2 statementThe reason lies in the fact that the threads worked with a shared resource, the console, without coordinating actions with each other. If the thread scheduler has allocated time to Thread-1, it instantly writes everything to the console. What other threads have already managed to write or have not managed to write there is unimportant. The result, as you can see, is deplorable. Therefore, in multi-threaded programming, a special concept of a mutex was introduced (from the English "mutex", "mutual exclusion" - "mutual exclusion") . Mutex task- provide such a mechanism that only one thread has access to an object at a certain time. If Thread-1 has captured the mutex of object A, other threads will not get access to it to change something in it. Until object A's mutex is released, other threads will have to wait. Real life example: imagine that you and 10 other strangers are participating in a training. You need to alternately express ideas and discuss something. But, since you are seeing each other for the first time, in order not to constantly interrupt each other and not slide into a hubbub, you use the “talking ball” rule: only one person can speak - the one who holds the ball. So the discussion turns out to be adequate and fruitful. So, the mutex, in fact, is such a ball. If an object's mutex is in the hands of a single thread, other threads will not be able to access work on this object. You don't have to do anything to create the mutex: it's already built into the classObject, which means every object in Java has one.

How the synchronized statement works in Java

Let's get acquainted with the new keyword - synchronized . They mark a certain piece of our code. If a block of code is marked with the synchronized keyword, it means that the block can only be executed by one thread at a time. Synchronization can be implemented in different ways. For example, create an entire synchronized method:
public synchronized void doSomething() {

   //...method logic
}
Or write a block of code where synchronization is carried out on some object:
public class Main {

   private Object obj = new Object();

   public void doSomething() {

       //...some logic available to all threads

       synchronized (obj) {

           //logic that is only available to one thread at a time
       }
   }
}
The meaning is simple. If one thread enters a block of code that is marked with the word synchronized, it instantly captures the object's mutex, and all other threads that try to enter the same block or method are forced to wait until the previous thread completes its work and releases the monitor. Thread synchronization.  synchronized statement - 3By the way! In the lectures of the course, you have already seen examples of synchronized, but they looked different:
public void swap()
{
   synchronized (this)
   {
       //...method logic
   }
}
The topic is new for you, and confusion with the syntax, of course, will be at first. Therefore, remember right away so as not to get confused later in the ways of writing. These two spellings mean the same thing:
public void swap() {

   synchronized (this)
   {
       //...method logic
   }
}


public synchronized void swap() {

   }
}
In the first case, you create a synchronized code block immediately upon entering the method. It is synchronized by object this, that is, by the current object. And in the second example, you hang up the word synchronized on the entire method. There is no longer any need to explicitly specify some object on which synchronization is carried out. Once a whole method is marked with a word, this method will automatically be synchronized for all objects of the class. We will not delve into the arguments, which way is better. For now, choose what you like best :) The main thing to remember is that a method can be declared synchronized only when all the logic inside it is executed by one thread at the same time. For example, in this case doSomething()it would be an error to make the method synchronized:
public class Main {

   private Object obj = new Object();

   public void doSomething() {

       //...some logic available to all threads

       synchronized (obj) {

           //logic that is only available to one thread at a time
       }
   }
}
As you can see, a piece of the method contains logic for which synchronization is not required. The code in it can be executed by several threads at the same time, and all critical places are allocated in a separate synchronized block. And one moment. Let's look "under the microscope" our example from the lecture with the exchange of names:
public void swap()
{
   synchronized (this)
   {
       //...method logic
   }
}
Please note: synchronization is carried out by this. That is, for a specific object MyClass. Imagine that we have 2 threads ( Thread-1and Thread-2) and only one object MyClass myClass. In this case, if Thread-1the method is called myClass.swap(), the object's mutex will be occupied, and Thread-2when you try to call it myClass.swap(), it will hang waiting for the mutex to be released. If we have 2 threads and 2 objects MyClass- myClass1and myClass2- on different objects, our threads can easily simultaneously execute synchronized methods. The first thread does:
myClass1.swap();
The second one does:
myClass2.swap();
In this case, the synchronized keyword inside the method swap()will not affect the operation of the program, since synchronization is carried out on a specific object. And in the latter case, we have 2 objects. Therefore, the threads do not create problems for each other. After all, two objects have 2 different mutexes, and their capture does not depend on each other.

Features of synchronization in static methods

But what if you need to synchronize a static method?
class MyClass {
   private static String name1 = "Olya";
   private static String name2 = "Lena";

   public static synchronized void swap() {
       String s = name1;
       name1 = name2;
       name2 = s;
   }

}
It is not clear what will act as a mutex in this case. After all, we have already decided that each object has a mutex. But the problem is that MyClass.swap()we don't need objects to call a static method: the method is static! So, what is next? :/ Actually, this is not a problem. The creators of Java took care of everything :) If the method, which contains the critical "multi-threaded" logic, is static, synchronization will be carried out by class. For greater clarity, the above code can be rewritten like this:
class MyClass {
   private static String name1 = "Olya";
   private static String name2 = "Lena";

   public static void swap() {

       synchronized (MyClass.class) {
           String s = name1;
           name1 = name2;
           name2 = s;
       }
   }

}
In principle, you could have thought of this on your own: since there are no objects, then the synchronization mechanism must somehow be “hardwired” into the classes themselves. So it is: you can also synchronize by class.
Comments
  • Popular
  • New
  • Old
You must be signed in to leave a comment
This page doesn't have any comments yet