A summary of locks in Java

Source: Internet
Author: User
Tags instance method volatile

Concurrent (thread-safe) issues arise when multiple processes or threads access the same resource at the same time (or in the same period). A lock can be used to resolve concurrency problems.

Built-in lock for Java:

Each Java object can be used as a lock that implements synchronization, which is called a built-in lock. When a thread enters a synchronous code block or method, the lock is automatically acquired, and the lock is freed when the synchronization code block or method exits. The only way to get a built-in lock is to enter this lock-protected synchronous code block or method. The Java built-in lock is a mutex, which means that at most one thread can get the lock, and when thread a tries to get the built-in lock held by thread B, thread A must wait or block until thread B releases the lock, and thread A will wait forever if thread B does not release the lock.

Object locks and class locks for Java:

Java's built-in locks can be basically divided into object locks and class locks, object locks are used for object instance methods, or on an object instance, and class locks are used for static methods of classes or class objects on classes. We know that there can be many object instances of a class, but each class has only one class object, so object locks for different object instances do not interfere with each other, but each class has only one class lock. One thing to note is that the class lock is just a conceptual thing, not real, it's just to help us understand the difference between a locked instance method and a static method.

Synchronized is just a locking mechanism for a built-in lock, and when a method is added to the Synchronized keyword, it indicates that the built-in lock is required to execute, and does not prevent other threads from accessing methods that do not need to obtain the built-in lock.

First, the use of synchronized

1, object Lock: The synchronization method is to lock the object, other threads will not be able to access the method and code block that need to get the object lock.

 Public class test{        publicsynchronizedvoid  print () {            System.out.println ( "Hello world!" );    }    }

2, object Lock: Synchronous code block, this writing is also locked the object, and the 1 effect, the other threads will not be able to access the method and code block to get the object lock.

 Public class test{        publicvoid  print () {            synchronized(this) {            System.out.println ("Hello world!" );        }    }    }

3, object Lock: Synchronous code block, this kind of writing locks the incoming object, does not affect the method that needs to obtain the current object lock and the code block access.

 public  class   test{ private  String a = "Test" ;  public  void   print () { synchronized   (a) {System.out.println (" Hello world! "         public  synchronized  void   Print1 () {System.out.println ( "123456" 

The

Executes the synchronization code block in print (), locks the object A, and takes care not to lock the test object, which means that the other synchronized methods and code blocks of the test object are not locked for print (). When the synchronization code block finishes executing, the lock on A is released.
to lock the code block of an object without affecting the high-performance notation of other synchronized blocks of the object:

 public  class   test{ private  byte  [] lock = new  byte  [0);  public  void   print () { synchronized   "Hello world!"         public  synchronized  void   Print1 () {System.out.println ( "123456" 

4, class Lock: for static methods.

 Public class test{        publicsynchronizedstaticvoid  print () {            System.out.println ("Hello world!" );    }    }

The effect is equivalent to synchronizing a block of code into the class object.

 Public class test{        publicvoid  print () {            synchronized(Test.class ) {            System.out.println ("Hello world!" );        }    }    }

The effect of the class lock adornment method and the code block is the same as the object lock, because the class lock is only an abstract concept, just to distinguish the characteristics of the static method, because the static method is common to all object instances, so the lock corresponding to the static method of synchronized modification is also unique, so abstract out a class lock. Class locks and object locks do not interfere with each other. Similarly, when a thread obtains an object lock, it can also get the lock, which is allowed by acquiring two locks at the same time.

Second, the release of the lock

Generally, after executing the synchronization code block (locked code block), release the lock, or you can use the Wait () method to release the lock halfway. Wait () way is like squatting in the toilet to half, suddenly found that the sewer blocked, had to come out to stand aside, so that the sewer master (ready to execute a thread of notify) into the toilet, dredge finished, the master shouted: "has been repaired" (notify), The comrade who had just come out heard the line again. Attention Ah, must wait for the teacher to come out Ah, the master does not come out, who also cannot enter. That is, after the notify, not the other threads can immediately enter the blockade area activity, but must also wait for the notify code in the blocking area after the completion of the lock to release, the other threads can enter.

Because the wait () operation and halfway out of the comrades will not be in line before the Notify signal, he will be watching the queue of people (including the plumber in it). Note that the master of Plumbing can not cut the queue, but also with those who go to the toilet in line, not to say that a person squat half out, repair the plumber can suddenly come out and then immediately rushed in to repair, he will be in line with the people who are fair competition, because he is also a normal thread. If the plumber is in the back, then the front of the people in, found plugging, wait, and then out to stand aside, and then go in a, wait, out, stand aside, until the master in the repair after the implementation of notify. In this way, a moment of kung fu, lined up next to stand a bunch of people, waiting for notify.

Finally, the master went in, then repaired, then notify, then?

1. There is a wait () person (thread) to be notified.
2. Why was he told that he was not another wait () person? Depends on the JVM. We cannot prejudge which one is to be notified. In other words, priority is not necessarily a priority to wake up, waiting for a long time is not necessarily a priority to wake up, all unpredictable! (Of course, if you know the implementation of the JVM, you can predict it.)
3. He (the thread being notified) wants to queue up again.
4. Will he be ranked in the first position of the team? The answer is: not necessarily. Is he going to end up in line? And not necessarily. But if the thread has a higher priority set, then the probability of his being in front of it is quite large.
5. When it is his turn to re-enter the toilet, he will proceed from the last Wait () and will not be re-executed. Disgusting Point said IS, he will continue to pull Baba, will not re-pull.
6. If the master Notifyall (). Then the pile of people who had come out of the queue were all re-queued, and the order was unknown.

Third, the use of lock

Use the Synchronized keyword to lock the resource. You can also use the lock keyword. It's what's new in JDK1.5.

 Public classBoundedbuffer {FinalLock lock =NewReentrantlock (); FinalCondition Notfull =lock.newcondition (); FinalCondition Notempty =lock.newcondition (); Finalobject[] Items =Newobject[100]; intputptr, Takeptr, Count;  Public voidPut (Object x)throwsinterruptedexception {lock.lock (); Try {             while(Count = =items.length) notfull.await (); ITEMS[PUTPTR]=x; if(++putptr = = items.length) putptr = 0; ++count;        Notempty.signal (); } finally{lock.unlock (); }    }     PublicObject Take ()throwsinterruptedexception {lock.lock (); Try {             while(count = = 0) notempty.await (); Object x=Items[takeptr]; if(++takeptr = = items.length) takeptr = 0; --count;            Notfull.signal (); returnx; } finally{lock.unlock (); }    }     }

(Note: This is an example of Javadoc, an implementation example of a blocking queue.) The so-called blocking queue is a queue that, if full or empty, causes the thread to block waiting. The Arrayblockingqueue in Java provides a ready-made blocking queue and does not need to write a specific one. )

The code between the Lock.lock () and Lock.unlock () of an object will be locked. This way is better than the synchronize where?

In a nutshell, the threads for wait are categorized. Using the toilet theory to describe, it is those who squat half and out of the toilet to wait for the reason may be different, some because the toilet is blocked, some because the toilet is out of water. Notice (notify), you can shout: Because the toilet is blocked and waiting to come back to the queue (for example, the toilet jam problem is solved), or shout, because the toilet is not water and waiting to come back to the queue (such as the toilet is not water problem solved). This can be controlled more finely. Unlike Synchronize's wait and notify, whether the toilet is clogged or the toilet is not water can only shout: just waiting to come in line! If the queue of people came in a look, found that the original is only a toilet jam problem solved, and their desire to solve the problem (toilet no water) has not been resolved, had to go back to wait (wait), white come in turn a circle, wasting time and resources.

Lock and synchronized correspondence:

Synchronized Wait Notify Notifyall
Lock Await Signal Signalall

Note: Do not call wait, notify, notifyall in blocks locked by lock mode.

Iv. use of volatile

The real problem with volatile is that the JVM is in-server mode (note that there is no problem with normal run mode), and the thread takes precedence over the value of the variable in its own thread-private stack instead of the value in the public heap, causing the variable value to be old. In other words, the volatile force requires all threads to get a value in the public memory heap when using volatile modified variables, and cannot be lazy to use their own. Volatile is absolutely not guaranteed to be atomic, and atomicity can only be achieved with the synchronized synchronous modifier.

We know that the operation of setting variable values in Java, except for long and double variables, is atomic, that is, there is no need for a simple read and write operation for variable values to be synchronized. Before JVM 1.2, Java's memory model implementations always read variables from main storage, without special attention. With the maturation and optimization of the JVM, the use of volatile keywords is now very important in multithreaded environments.

In the current Java memory model, threads can store variables in local memory (such as the machine's registers), rather than read and write directly in main storage. This can cause a thread to modify the value of one variable in main memory, while another thread continues to use its copy of the variable value in the register, resulting in inconsistent data. to solve this problem, simply declare the variable to be volatile (unstable), which indicates that the JVM is not stable, and each time it is used, it is read in main memory. Generally speaking, the flags shared between tasks in a multitasking environment should be modified with a volatile modifier.

A volatile-modified member variable forces the value of the member variable to be reread from shared memory each time it is accessed by the thread. Also, when a member variable changes, forcing the thread to write the change back to the shared memory. So at any moment, two different threads always see the same value for a member variable.

The Java language specification states that for optimal speed, a thread is allowed to save a private copy of a shared member variable, and is compared to the original value of a shared member variable only if the thread enters or leaves the synchronized code block. This way, when multiple threads interact with an object at the same time, it is important to notice that the thread gets the changes to the shared member variables in a timely manner. The volatile keyword is a hint to the VM: You cannot save its private copy for this member variable, but you should interact directly with the shared member variable.

Usage Recommendation: Use volatile on member variables accessed by two or more threads. You do not have to use the variable you want to access when it is already in a synchronized code block, or is a constant. It is inefficient to use volatile to mask the necessary code optimizations in the VM, so use this keyword when necessary.

A summary of locks in Java

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.