To] Java multi-thread synchronization

Source: Internet
Author: User
Tags semaphore
Endless learning is a pleasure. [Switch] Java multi-thread synchronization

From: http://hi.baidu.com/myicer/blog/item/b376452ca5ee82ee8a1399bd.html

An example of understanding wait () and Policy ()
Link: http://blog.csdn.net/xm4014/archive/2003/01/28/14714.aspx

The following is a post I saw on the csdn forum, which involves the understanding of synchronization, wait (), notify (), and other concepts, I tried to analyze the wait () and Policy () methods based on some original replies and related concepts in think in Java. Thank you for your advice.

The problem is as follows:

File: // analyze this program and explain it. here we will focus on synchronized, wait (), notify. Thank you!
Class threada
{
Public static void main (string [] ARGs)
{
Threadb B = new threadb ();
B. Start ();
System. Out. println ("B is start ....");
Synchronized (B) // What does B in parentheses mean and what does it do?
{
Try
{
System. Out. println ("waiting for B to complete ...");
B. Wait (); // What does this sentence mean?
System. Out. println ("completed. Now back to main thread ");
} Catch (interruptedexception e ){}
}
System. Out. println ("total is:" + B. Total );
}
}

Class threadb extends thread
{
Int total;
Public void run ()
{
Synchronized (this)
{
System. Out. println ("threadb is running ..");
For (INT I = 0; I <100; I ++)
{
Total + = I;
System. Out. println ("total is" + total );
}
Notify ();
}
}
}

To analyze this program, we must first understand y () and wait (). Why didn't we record these two methods when recording the thread a few days ago, because these two methods are not in the Thread class, it belongs to the underlying object base class. That is to say, not only is thread, but every object has the functions of notify and wait. Why? Because they are used to manipulate the lock, and each object has a lock, the lock is the basis of each object. Since the lock is the basis, the method of manipulating the lock is of course the most basic.

Let's take a look at it. First, we 'd better review Part 1 of think in Java 14.3.1: waiting and notification, that is, wait () and policy.

According to think in Java, "Wait () allows us to put threads into the" Sleep "state, while actively waiting for conditions to change. in addition, the thread will be awakened only when one notify () or notifyall () Change and check whether the conditions have changed."

Let's explain this sentence.
"Wait () allows us to put the thread into the" Sleep "State. That is to say, wait also blocks the current thread, which is the same as sleep or suspend. what is the difference between it and sleep and suspend?

The difference is that "(wait) and" actively "wait for conditions to change", this is critical, and sleep and suspend cannot do it. because we sometimes need the help of synchronized to prevent conflicts between threads. Once synchronization is used, the object is locked, that is, the object lock is obtained, other threads that want to use the object lock can only wait in the queue and wait until the synchronization method or all the programs in the synchronization block have run. in the synchronization method and synchronization block, neither sleep () nor suspend () can be unlocked when they are called by themselves. They all occupy the used object lock.
However, wait does. It allows the synchronization method or synchronization block to temporarily discard the object lock and temporarily give it to other persons who need the object lock (Here it should be a program block or thread) for use, this means that other Synchronization Methods in the thread object can be called during wait () execution! In other cases (sleep, suspend), this is impossible.
But pay attention to what I mentioned above. I just temporarily give up the object lock and use it for other threads. The thread where my wait is located still needs to reclaim this object lock. What is wait? It's wait. I can get it back when someone else finishes using it!
Well, how can we take back the object lock?
The first method is to limit the lending time. set the parameter in wait (), for example, wait (1000). in milliseconds, it indicates that I only lent out for 1 second. After one second, I automatically took it back.
The second method is to let the borrower inform me that he has used up his work and will return it to me. at this time, I will immediately withdraw it. ah, what if I took it back one hour later and it took only half an hour for someone else to finish it? Depend! Of course, it will be recovered after it is used up. It also determines how long it will take.

So how can someone tell me? I believe everyone can think of it, notify (), this is the last sentence "and only when a notify () or notifyall () changes, the thread will be awakened.
Therefore, we can place a wait () and Policy () in any synchronous method or within the synchronization block, regardless of whether the class is prepared for thread-related processing. In fact, we can only call wait () and Policy () in the synchronous method or block ().

At this time, it is easy to explain the above program.

Synchronized (B) {...}; defines a synchronization block and uses B as the resource lock. B. wait (); Means to temporarily release the lock and block the current thread, so that other threads that use the same lock have the opportunity to execute it. Here, the thread B must use the same lock. after this thread is executed to a certain point, it notifies the wait thread by running y (). The lock is used up. After the synchronization block in which notify () is running, the thread where wait is located can continue the execution.

 

 

Java multi-threaded Design of wait/notify Mechanism

Coordination is required between multiple threads. For example, if displaythread of a browser that displays an image wants to execute the task of displaying the image, it must wait for the download thread downloadthread to download the image. If the image has not been downloaded, displaythread can be paused. After downloadthread completes the task, it notifies displaythread that "the image is ready and displayed". At this time, displaythread continues to run.

The above logic simply says: if the conditions are not met, wait. When the condition is met, the thread waiting for the condition will be awakened. In Java, the implementation of this mechanism depends on wait/notify. The wait and lock mechanisms are closely related. For example:

Synchronized (OBJ ){
While (! Condition ){
OBJ.Wait ();
}
OBJ. dosomething ();
}

After thread a acquires the OBJ lock, it finds that the condition is not met and cannot continue the next processing. Therefore, thread a is wait ().

In another thread B, if B modifies some conditions so that the condition of thread a is met, thread A can be awakened:

Synchronized (OBJ ){
Condition = true;
OBJ. Y ();
}

Note the following concepts:

# The OBJ lock must be obtained before calling the wait () and notify () Methods of OBJ, that is, it must be written in the code segment of synchronized (OBJ.

# Call obj. after wait (), thread a releases the OBJ lock. Otherwise, thread B cannot obtain the OBJ lock, and it cannot be in synchronized (OBJ ){...} wake up a in the code segment.

# After the obj. Wait () method is returned, thread a needs to obtain the OBJ lock again to continue execution.

# If both A1, A2, and A3 are in OBJ. wait (), B calls obj. notify () can only wake up one of A1, A2, and A3 (which one is determined by JVM ).

# Obj. notifyall () can all wake up A1, A2, A3, but continue to execute obj. the next statement of wait () must obtain the OBJ lock. Therefore, only one of A1, A2, and A3 has the opportunity to obtain the lock for further execution. For example, A1, the rest can be executed only after A1 releases the OBJ lock.

# When B calls obj. Y/policyall, B is holding the OBJ lock. Therefore, although A1, A2, and A3 are awakened, they still cannot obtain the OBJ lock. After B exits the synchronized block and releases the OBJ lock, only one of A1, A2, and A3 will have the opportunity to obtain the lock and continue execution.

 

Four synchronized usage

1. used for method declaration, placed after the range operator (public, etc.), before the return type declaration (void, etc. that is, only one thread can enter this method at a time. If other threads want to call this method at this time, they can only wait in queue. After the current thread (that is, the thread inside the Synchronized Method) executes this method, other threads can enter.

For example:

Public synchronized void synmethod (){
// Method body
}

2. For a code block, synchronized is followed by parentheses and contains variables. In this way, only one thread enters the code block at a time. For example:

Public int synmethod (INT A1 ){
Synchronized (A1 ){
// Only one thread can enter
}
}
3. Synchronized is followed by an object in parentheses. At this time, the thread obtains an object lock. For example:

Public class mythread implements runnable {
Public static void main (string ARGs []) {
Mythread Mt = new mythread ();
Thread T1 = new thread (MT, "T1 ");
Thread t2 = new thread (MT, "T2 ");
Thread T3 = new thread (MT, "T3 ");
Thread t4 = new thread (MT, "T4 ");
Thread T5 = new thread (MT, "T5 ");
Thread T6 = new thread (MT, "T6 ");
T1.start ();
T2.start ();
T3.start ();
T4.start ();
T5.start ();
T6.start ();
}

Public void run (){
Synchronized (this ){
System. Out. println (thread. currentthread (). getname ());
}
}
}


For 3, if the thread enters, the object lock will be obtained, and no operations can be performed by other threads on all objects of this class. locking at the object level is usually a rough method. Why is it necessary to lock the entire object and not allow other threads to temporarily use other Synchronization Methods in the object to access Shared resources? If an object has multiple resources, you do not need to lock all threads out to allow a thread to use some of the resources. Because each object has a lock, you can use a virtual object to lock it as follows:

Class finegrainlock {

Mymemberclass X, Y;
Object xlock = new object (), ylock = new object ();

Public void Foo (){
Synchronized (xlock ){
// Access X here
}

// Do something here-but don't use shared resources

Synchronized (ylock ){
// Access y here
}
}

Public void bar (){
Synchronized (this ){
// Access both X and Y here
}
// Do something here-but don't use shared resources
}
}

4. Synchronized is followed by a class in brackets. For example:

Class arraywithlockorder {
Private Static long num_locks = 0;
Private long lock_order;
Private int [] arr;

Public arraywithlockorder (INT [])
{
Arr =;
Synchronized (arraywithlockorder. Class) {// ------------------------------------------- here
Num_locks ++; // Number of locks plus 1.
Lock_order = num_locks; // set a unique lock_order for this object instance.
}
}
Public long lockorder ()
{
Return lock_order;
}
Public int [] array ()
{
Return arr;
}
}

Class someclass implements runnable
{
Public int sumarrays (arraywithlockorder A1,
Arraywithlockorder A2)
{
Int value = 0;
Arraywithlockorder first = A1; // reserve
Arraywithlockorder last = a2; // local copy.
Int size = a1.array (). length;
If (size = a2.array (). length)
{
If (a1.lockorder ()> a2.lockorder () // confirm and set the object lock
{// Order.
First = a2;
Last = A1;
}
Synchronized (first) {// lock objects in the correct order.
Synchronized (last ){
Int [] arr1 = a1.array ();
Int [] arr2 = a2.array ();
For (INT I = 0; I value + = arr1 [I] + arr2 [I];
}
}
}
Return value;
}
Public void run (){
//...
}
}

For thread 4, if the thread enters, all operations of the thread in this class cannot be performed, including static variables and static methods. In fact, for synchronization of code blocks containing static methods and static variables, we usually use 4 to lock.

Relationship between the above four types:

A lock is associated with an object. Each object has a lock. To execute the synchronized statement, the thread must be able to obtain the lock of the object specified by the expression in the synchronized statement. An object has only one lock, after being obtained by a thread, it no longer owns the lock. After the thread executes the synchronized statement, it returns the lock to the object.
You can declare a method as a synchronous method by adding the synchronized modifier before the method. The synchronization method obtains a lock before execution. If this is a class method, the obtained lock is the class Object lock related to the class of the declared method. If this is an instance method, the lock is the lock of this object.

 

The following describes some common methods:

Wait (), wait (long), Y (), policyall () and other methods are the instance methods of the current class,

Wait () is used to release the lock for the thread holding the object lock;
Wait (long) is used to obtain the lock again after the thread holding the object lock is released for long (milliseconds). Wait () is equivalent to wait (0;
Y () is to wake up a thread waiting for the lock of this object. If there are more than one waiting thread, the wake-up thread is determined by JVM;
Policyall is used to wake up all threads waiting for the lock of this object.
Here I also reiterate that we should first use the yyall () method, because it is easier for the JVM to find the most appropriate thread to wake up than to wake up a thread.

The preceding method can only be used in the current thread. Otherwise, the runtime error java. Lang. illegalmonitorstateexception: current thread not owner is reported.

 

Next, let's talk about the relationships between synchronized, wait (), and notify:

1. Where synchronized exists, wait and notify may not be available.

2. with wait, synchronized must be used in zooy. this is because wait and notify are not thread classes, but methods that every object has. Moreover, these two methods are related to the object lock. Where there is a lock, there must be synchronized.

In addition, note that if you want to use the notify and wait methods together, you must first call notify and then call wait, this thread is no longer the current thread. For example:

/**
* Title: jdeveloper's Java projdect
* Description: N/
* Copyright: Copyright (c) 2001
* Company: Soho http://www.ChinaJavaWorld.com.
* @ Author
Jdeveloper@21cn.com
* @ Version 1.0
*/
Import java. Lang. runnable;
Import java. Lang. thread;

Public class demothread
Implements runnable {

Public demothread (){
Testthread testthread1 = new testthread (this, "1 ");
Testthread testthread2 = new testthread (this, "2 ");

Testthread2.start ();
Testthread1.start ();

}

Public static void main (string [] ARGs ){
Demothread demothread1 = new demothread ();

}

Public void run (){

Testthread t = (testthread) thread. currentthread ();
Try {
If (! T. getname (). inclusignorecase ("1 ")){
Synchronized (this ){
Wait ();
}
}
While (true ){

System. Out. println ("@ time in thread" + T. getname () + "=" +
T. increasetime ());

If (T. gettime () % 10 = 0 ){
Synchronized (this ){
System. out. println ("************************************* ***");
Notify ();
If (T. gettime () = 100)
Break;
Wait ();
}
}
}
}
Catch (exception e ){
E. printstacktrace ();
}
}

}

Class testthread
Extends thread {
Private int time = 0;
Public testthread (runnable R, string name ){
Super (R, name );
}

Public int gettime (){
Return time;
}

Public int increasetime (){
Return ++ time;
}

}

The following describes the relationship between producers and consumers:

Public class test {
Public static void main (string ARGs []) {
Semaphore S = new semaphore (1 );
Thread T1 = new thread (S, "producer1 ");
Thread t2 = new thread (S, "producer2 ");
Thread T3 = new thread (S, "producer3 ");
Thread t4 = new thread (S, "consumer1 ");
Thread T5 = new thread (S, "consumer2 ");
Thread T6 = new thread (S, "consumer3 ");
T1.start ();
T2.start ();
T3.start ();
T4.start ();
T5.start ();
T6.start ();
}
}

Class semaphore
Implements runnable {
Private int count;
Public semaphore (int n ){
This. Count = N;
}

Public synchronized void acquire (){
While (COUNT = 0 ){
Try {
Wait ();
}
Catch (interruptedexception e ){
// Keep trying
}
}
Count --;
}

Public synchronized void release (){
While (COUNT = 10 ){
Try {
Wait ();
}
Catch (interruptedexception e ){
// Keep trying
}
}
Count ++;
Policyall (); // alert a thread that's blocking on this semaphore
}

Public void run (){
While (true ){
If (thread. currentthread (). getname (). substring (0, 8). inclusignorecase ("consumer ")){
Acquire ();
}
Else if (thread. currentthread (). getname (). substring (). equalsignorecase ("producer ")){
Release ();
}
System. Out. println (thread. currentthread (). getname () + "" + count );
}
}
}

There is generally no conflict between producer production and consumer consumption, but when the inventory is 0, the consumer cannot consume it, but when the inventory is the upper limit (10 here, producers cannot produce either. please study the above program, and you will certainly make a lot better than before.

The code above demonstrates that synchronized has no absolute relationship with wait and notify. In the methods and code blocks declared by synchronized, you do not need to use methods such as wait and notify. However, if a thread has a certain contention for a certain resource, you must put the thread into waiting or waking up in due time.

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.