Parsing thread safety and synchronized usage in Java threading programming _java

Source: Internet
Author: User
Tags instance method mutex

A. When will there be thread safety issues?

Thread-safe issues do not occur in a single thread. In multithreaded programming, it is possible to have simultaneous access to the same resource, which can be a variety of resources: A variable, an object, a file, a database table, and so on, and when multiple threads simultaneously access the same resource, There is a problem:

Because each thread executes a process that is not controllable, it is likely to cause the final result to go against the actual desire or to cause a program error directly.

For a simple example:

There are now two threads that read data from the network and then insert a database table, requiring that duplicate data not be inserted.

Then there must be two actions in the process of inserting data:

1) Check whether the data exists in the database;

2 If it exists, it is not inserted, and if it does not exist, it is inserted into the database.

This can happen if two threads are represented by thread-1 and thread-2, and at some point, both thread-1 and thread-2 read the data x:

Thread-1 to check if there is a data x in the database, and then thread-2 to check if there is a data x in the database.

As a result, the result of two thread checks is that there is no data x in the database, then two threads insert the data x into the database table separately.

This is a thread-safety issue where multiple threads simultaneously access a resource, causing the program to run results that are not what you want to see.

Within this, this resource is called a critical resource (also known as a shared resource).

That is, when multiple threads simultaneously access a critical resource (an object, a property in an object, a file, a database, and so on), thread-safety issues can arise.

However, when multiple threads execute a method, local variables inside the method are not critical resources because the methods are executed on the stack, and the Java stack is thread-private, so there is no thread-safety issue.

Two. How do I troubleshoot thread safety issues?

So generally speaking, how to solve the problem of thread safety?

Basically all concurrency patterns address thread-safety issues with a "serialized access critical resource" scenario where only one thread accesses a critical resource, also known as synchronous mutex access, at the same time.

Typically, a lock is added to the code that accesses the critical resource, freeing the lock when the critical resource is accessed and allowing other threads to continue accessing it.

In Java, there are two ways to implement synchronous mutex access: synchronized and lock.

This article mainly describes the use of synchronized, the use of lock is described in the next blog post.

Three. Synchronized sync method or sync block

Before we know how to use the Synchronized keyword, let's look at a concept: a mutex, as the name implies: a lock that reaches a mutually exclusive access purpose.

As a simple example: if you add a mutex to a critical resource, when a thread accesses the critical resource, the other threads can only wait.

In Java, each object has a lock tag (monitor), also known as a monitor, when multithreading accesses an object at the same time, the thread can only access it if it acquires a lock on the object.

In Java, you can use the Synchronized keyword to mark a method or block of code, and when a thread calls the object's synchronized method or accesses the synchronized code block, the thread obtains the lock on the object. Other threads are temporarily unable to access this method, and the thread will not release the lock of the object until the method is finished or the code block executes, and other threads can execute the method or block of code.

Here are a few simple examples to illustrate the use of the Synchronized keyword:

1.synchronized method

In the following code, two threads invoke the InsertData object to insert data separately:

public class Test {public
 
  static void Main (string[] args) {
    final insertdata insertdata = new InsertData ();
     
    New Thread () {public
      void run () {
        Insertdata.insert (Thread.CurrentThread ());
    Start ();
     
     
    New Thread () {public
      void run () {
        Insertdata.insert (Thread.CurrentThread ());
    Start ();
  }
 
Class InsertData {
  private arraylist<integer> ArrayList = new arraylist<integer> ();
   
  public void Insert (thread thread) {
    for (int i=0;i<5;i++) {
      System.out.println (thread.getname () + "inserting data" + i);
      Arraylist.add (i);
    }}}

The output of this program is:

Describes two threads executing the Insert method at the same time.

And if you precede the Insert method with the keyword synchronized, the result is:

Class InsertData {
  private arraylist<integer> ArrayList = new arraylist<integer> ();
   
  Public synchronized void Insert (thread thread) {for
    (int i=0;i<5;i++) {
      System.out.println thread.getname ( + "Insert data" +i);
      Arraylist.add (i);
    }}}

The output from the above indicates that the THREAD-1 insert data is not performed until after the Thread-0 is inserted into the data. Explains that Thread-0 and Thread-1 are sequentially executing the Insert method.

This is the synchronized method.

However, there are a few points to note:

1 when a thread is accessing the Synchronized method of an object, other threads cannot access other synchronized methods of the object. The reason for this is simple, because an object has only one lock, and when a thread acquires the lock on the object, the other thread cannot get the lock on the object, so the other synchronized methods of the object cannot be accessed.

2 when a thread is accessing the Synchronized method of an object, other threads can access the object's Synchronized method. The reason for this is simple, access to a synchronized method does not require a lock on the object, if a method does not use the Synchronized keyword decoration, it will not be used to the critical resources, then other threads can access this method,

3 If a thread a needs to access the Synchronized method Fun1 of the object Object1, another thread B needs to access the Synchronized method Fun1 of the object object2, even if the Object1 and Object2 are the same type), Also does not create thread-safety issues because they are accessing different objects, so there is no mutex problem.

2.synchronized code block

The synchronized code block resembles the following form:

Synchronized (synobject) {

}
When this block of code is executed in a thread, the thread acquires the lock of the object Synobject, which makes it impossible for other threads to access the code block at the same time.

Synobject can be this, representing the lock that gets the current object, or a property in the class that represents the lock that gets the property.

For example, the above insert method can be changed to the following two kinds of forms:

Class InsertData {
  private arraylist<integer> ArrayList = new arraylist<integer> ();
   
  The public void Insert (thread thread) {
    synchronized (this) {A for
      (int i=0;i<100;i++) {
        System.out.println ( Thread.getname () + "Insert Data" +i);
        Arraylist.add (i);
      }

}} Class InsertData {
  private arraylist<integer> ArrayList = new arraylist<integer> ();
  Private object = new Object ();
   
  public void Insert (thread thread) {
    synchronized (object) {for
      (int i=0;i<100;i++)
        { System.out.println (Thread.getname () + "in inserting data" +i);
        Arraylist.add (i);
      }}}


As you can see from the above, synchronized code blocks are much more flexible to use than synchronized methods. Because perhaps only a portion of the code in a method needs to be synchronized, if you synchronize the entire method with synchronized at this time, it will affect program execution efficiency. The problem can be avoided by using synchronized code blocks, where synchronized code blocks can be implemented to synchronize only where synchronization is needed.

In addition, each class also has a lock that can be used to control concurrent access to static data members.

And if a thread executes an object's synchronized method, and another thread needs to execute the static synchronized method of the class to which the object belongs, there is no mutex at this point because the access static The synchronized method occupies a class lock, while access to the non-static synchronized method occupies an object lock, so there is no mutex.

Look at the code below to see:

public class Test {public
 
  static void Main (string[] args) {
    final insertdata insertdata = new InsertData ();
    New Thread () {
      @Override public
      void Run () {
        insertdata.insert ();
      }
    }. Start (); 
    New Thread () {
      @Override public
      void Run () {
        insertdata.insert1 ();
      }
    }. Start ();
  }
 
Class InsertData {public 
  synchronized void Insert () {
    System.out.println ("execute Insert");
    try {
      Thread.Sleep (5000);
    } catch (Interruptedexception e) {
      e.printstacktrace ();
    }
    System.out.println ("Execute insert Complete");
  }
   
  Public synchronized static void Insert1 () {
    System.out.println ("Execute Insert1");
    System.out.println ("Execute insert1 Complete");
  }

implementation results;

The Insert method is executed inside the first thread and does not cause the second thread to perform a blocking behavior on the Insert1 method.

Let's take a look at what the Synchronized keyword does, and we'll reverse-compile its bytecode look, the following code decompile the bytecode:

public class InsertData {
  Private object = new Object ();
   
  public void Insert (thread thread) {
    synchronized (object) {
     
    }
  } public
   
  synchronized void Insert1 (thread Thread) {
     
  } public
   
  void Insert2 (thread thread) {
     
  }
}

The byte code obtained from the decompile shows that the synchronized code block actually has more than Monitorenter and monitorexit two instructions. Monitorenter instruction execution will let the object lock count plus 1, and monitorexit instruction execution will let the object lock count minus 1, in fact, this and operating system inside the PV operation is very much like the operating system inside the PV operation is used to control the access of multiple threads to the critical resources. For the SYNCHRONIZED method, the thread in the execution recognizes that the method's METHOD_INFO structure has acc_synchronized tag settings, and then it automatically acquires the lock on the object, invokes the method, and finally releases the lock. If an exception occurs, the thread automatically releases the lock.

One thing to note: For the Synchronized method or the synchronized code block, when an exception occurs, the JVM automatically releases the lock occupied by the current thread and therefore does not cause a deadlock because of the exception.

Three. Other noteworthy areas of the synchronized

The difference between 1.synchronized and static synchronized
synchronized is a lock on the current instance of a class, preventing other threads from accessing all the synchronized blocks of that instance of the class at the same time, noting that this is "the current instance of the class", with two different instances of the class having no such constraint. So the static synchronized happens to control access to all instances of the class, and the static synchronized is to restrict the thread from simultaneously accessing all instances of the class in the JVM while accessing the corresponding code quickly. In fact, there is a synchronized in a method or a block of code in a class, then after generating an instance of that class there is also a monitoring fast, placing the thread concurrent access to the instance synchronized protection fast, and static Synchronized is all instances of the class common one monitoring fast, that is, the difference between the two, that is, synchronized equivalent to this.synchronized, and
Static synchronized is equivalent to something.synchronized.
A Japanese author-Hao's "Java Multithreaded design pattern" has such an article:
  

Pulbic class Something () {public
synchronized void Issynca () {} public
synchronized void Issyncb () {}
Publ IC static synchronized void Csynca () {} public
static synchronized void Csyncb () {}
}

So, if you add two instances of the something Class A and B, how can the following group of methods be accessed by more than 1 threads at the same time?
A. X.issynca () and X.ISSYNCB ()
B. X.issynca () and Y.issynca ()
C. X.csynca () and Y.CSYNCB ()
D. X.issynca () and Something.csynca ()
Here, it is clear to judge:
A, all are access to the synchronized domain of the same instance and cannot be accessed concurrently
b, it's for different instances, so it can be accessed at the same time
C, because it is a static synchronized, the different instances are still limited, equivalent to Something.issynca () and SOMETHING.ISSYNCB (), and therefore cannot be accessed concurrently.
So what about the d?, the answer to the book is that it can be accessed at the same time, and the answer is synchronzied is the reason why the instance method and the Synchronzied class method are different because of lock (lock).
Personal analysis is synchronized and static synchronized is equivalent to two gangs, each of them, each other without constraints, can be simultaneous access. It is not yet clear how the Java internal Design synchronzied is implemented.
Conclusion: a:synchronized Static is the scope of a class, synchronized static csync{} prevents multiple threads from simultaneously accessing the synchronized static method in this class. It can work on all object instances of a class.
B:synchronized is the scope of an instance, synchronized Issync () {} prevents multiple threads from simultaneously accessing the Synchronized method in this instance.
2.synchronized method and synchronized Code fast Difference
There is no difference between synchronized methods () {} and synchronized (this) {}, but synchronized methods () {} is easy to read and synchronized (this) {} More precise control of the conflict limits access to the region, and sometimes more efficient performance.
The 3.synchronized keyword is not inherited

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.