Lock use __synchronize for object

Source: Internet
Author: User
Tags static class try catch

In the previous article, the producers and consumers were implemented with condition, in which the condition await and singal were used, and this implementation was particularly similar to the lock of object, if the lock mechanism of object was used to realize the producers and consumers, as follows:

ImportJava.util.Date;ImportJava.util.concurrent.ExecutorService;ImportJava.util.concurrent.Executors;
 /** * Created by Lizhiqiang on 2016/12/23. */Public classTestObjectLock2 {Public static voidMain (string[] args) {FinalBoundedbuffer buffer =NewBoundedbuffer ();

        Executorservice service = Executors.newfixedthreadpool (2); Service.execute (NewRunnable () {@OverridePublic voidRun () { while(true){Try{Thread.CurrentThread (). Sleep (1000); }Catch(Interruptedexception e)
                    {E.printstacktrace ();
                } buffer.put (1);
        }
            }
        }); Service.execute (NewRunnable () {@OverridePublic voidRun () { while(true) {System. out. println (NewDate () +":" + Buffer.take ());
        }
            }
        });
    Service.shutdown (); }Public Static Classboundedbuffer{ObjectNotempty=NewObject (); ObjectNotfull=NewObject ();FinalObject[]Items=NewOBJECT[3];intCount; PublicBoundedbuffer () {Count= 0; }Public voidPut (Object x) {synchronized(Notfull){if(Count==2) {Try{Notfull. Wait (); }Catch(Interruptedexception e)
                    {E.printstacktrace (); }
                }synchronized(Notempty){
                    ++Count;Items[Count] = x;Notempty. Notify (); }
            }
        } PublicObject Take () {object result;synchronized(Notempty){if(Count==0) {Try{Notempty. Wait (); }Catch(Interruptedexception e) {
                    }
                }synchronized(Notfull) {result =Items[Count--];Notfull. Notify (); } returnResult }
        }
    }
}
Execution results:

Fri Dec 11:07:20 CST 2016:1
Fri Dec 11:07:21 CST 2016:1
Fri Dec 11:07:22 CST 2016:1
Fri Dec 11:07:23 CST 2016:1
Fri Dec 11:07:24 CST 2016:1
Fri Dec 11:07:25 CST 2016:1
Fri Dec 11:07:26 CST 2016:1

The discovery effect is the same as the previous one.


Here are two questions to start with:

1. How to achieve multiple consumers and multiple producers with condition or object.

What is the difference between 2.Condition and object?


1. How to achieve multiple consumers and multiple producers with condition or object.

Condition implementation:

ImportJava.util.Date;ImportJava.util.concurrent.ExecutorService;ImportJava.util.concurrent.Executors;ImportJava.util.concurrent.locks.Condition;ImportJava.util.concurrent.locks.Lock;ImportJava.util.concurrent.locks.ReentrantLock;
 /** * Created by Lizhiqiang on 2016/12/23. */Public classTestCondition3 {Public static voidMain (string[] args) {FinalBoundedbuffer buffer =NewBoundedbuffer ();
        Executorservice service = Executors.newfixedthreadpool (4); Service.execute (NewRunnable () {@OverridePublic voidRun () { while(true) {buffer.put (1);
        }
            }
        }); Service.execute (NewRunnable () {@OverridePublic voidRun () { while(true) {System. out. println ("Consumers"+thread.currentthread (). GetName () +":"+NewDate () +":" + Buffer.take ());
        }
            }
        }); Service.execute (NewRunnable () {@OverridePublic voidRun () { while(true) {System. out. println ("Consumers"+thread.currentthread (). GetName () +":"+NewDate () +":" + Buffer.take ());
        }
            }
        }); Service.execute (NewRunnable () {@OverridePublic voidRun () { while(true) {System. out. println ("Consumers"+thread.currentthread (). GetName () +":"+NewDate () +":" + Buffer.take ());
        }
            }
        });
    Service.shutdown (); }Public Static Classboundedbuffer{FinalLockLock=NewReentrantlock (); ConditionNotempty=Lock. Newcondition (); ConditionNotfull=Lock. Newcondition ();FinalObject[]Items=NewOBJECT[3];intCount; PublicBoundedbuffer () {Count= 0; }Public voidPut (Object x) {Lock. Lock ();if(Count==2) {Try{Notfull. await (); }Catch(Interruptedexception e)
                {E.printstacktrace (); }
            }
            ++Count;Items[Count] = x;Notempty. signal ();Lock. Unlock (); } PublicObject Take () {Lock. Lock (); Object result;if(Count==0) {Try{Notempty. await (); }Catch(Interruptedexception e) ({}} result =Items[Count--];Notfull. signal ();Lock. Unlock (); returnResult }
    }
}
Object implementation:

ImportJava.util.Date;ImportJava.util.concurrent.ExecutorService;ImportJava.util.concurrent.Executors;
 /** * Created by Lizhiqiang on 2016/12/23. */Public classTestObjectLock3 {Public static voidMain (string[] args) {FinalBoundedbuffer buffer =NewBoundedbuffer ();

        Executorservice service = Executors.newfixedthreadpool (4); Service.execute (NewRunnable () {@OverridePublic voidRun () { while(true) {buffer.put (1);
        }
            }
        }); Service.execute (NewRunnable () {@OverridePublic voidRun () { while(true) {System. out. println ("Consumers"+thread.currentthread (). GetName () +":"+NewDate () +":" + Buffer.take ());
        }
            }
        }); Service.execute (NewRunnable () {@OverridePublic voidRun () { while(true) {System. out. println ("Consumers"+thread.currentthread (). GetName () +":"+NewDate () +":" + Buffer.take ());
        }
            }
        }); Service.execute (NewRunnable () {@OverridePublic voidRun () { while(true) {System. out. println ("Consumers"+thread.currentthread (). GetName () +":"+NewDate () +":" + Buffer.take ());
        }
            }
        });
    Service.shutdown (); }Public Static Classboundedbuffer{ObjectNotempty=NewObject (); ObjectNotfull=NewObject ();FinalObject[]Items=NewOBJECT[3];intCount; PublicBoundedbuffer () {Count= 0; }Public voidPut (Object x) {synchronized(Notfull){if(Count==2) {Try{Notfull. Wait (); }Catch(Interruptedexception e)
                    {E.printstacktrace (); }
                }synchronized(Notempty){
                    ++Count;Items[Count] = x;Notempty. Notify (); }
            }
        } PublicObject Take () {object result;synchronized(Notempty){if(Count==0) {Try{Notempty. Wait (); }Catch(Interruptedexception e) {
                    }
                }synchronized(Notfull) {result =Items[Count--];Notfull. Notify (); } returnResult }
        }
    }
}
All of the above two implementations implement the problem of a producer multiple consumers, but the execution will error: array out of bounds

Why.

The reason is that after Singal and notify, the corresponding thread is not executed immediately, but instead the CPU gets the corresponding thread from the waiting pool, and then the context switch begins to execute the corresponding thread. For example, producers to produce a product, inform consumer A, at this time, the producer began to produce a second product, inform Consumer B, consumer A and B, while the implementation of a faster, consumption of two products, resulting in B a product also can not get, resulting in array out of bounds.

Workaround:

Let the producer wait for a while to notify another consumer, let the consumer have sufficient time to execute, and again into the waiting. But this thinking leads to inefficient producers because at the same time it only allows a consumer to execute.

In producer code if the wait time:

Service.execute (Runnable () {
    @Override
    Run () {while
        (true) {
             {
                thread.currentthread (). Sleep (m);
             (interruptedexception e) {
                e.printstacktrace ();
            }
            Buffer.put (1);
        }}}
);
Another idea:

Let the consumer take after a sleep for a while, this is more in line with the actual scene.


Multi-producer and consumer scenarios.
The addition of wait time does not solve the problem of such arrays being out of bounds, and can only be eaten by using a try catch to get the array out of bounds.

Let's discuss the second content below:

What is the difference between synchronize and lock, and why is there a lock to synchronize?

First, synchronize cannot resolve deadlock problems that occur with multiple object locks.

For example, in our case above,

Public voidPut (Object x) {synchronized(Notfull){if(Count==2) {Try{System. out. println ("The product library is full.");Notfull. Wait (); System. out. println ("can add a product, currently has"+Count+"a"); }Catch(Interruptedexception e)
            {E.printstacktrace (); } System. out. println ("producer"+thread.currentthread (). GetName ());synchronized(Notempty) {System. out. println ("To add a product, there is currently"+Count+"a"); ++Count;Items[Count] = x; System. out. println ("finished adding products, currently has"+Count+"a");Notempty. Notify (); }
    }
} PublicObject Take () {object result;synchronized(Notempty){if(Count==0) {Try{System. out. println ("no product.");Notempty. Wait (); System. out. println ("There's a product."); }Catch(Interruptedexception e) {}} System. out. println ("Consumers"+thread.currentthread (). GetName ());synchronized(Notfull) {System. out. println ("To get the product, there are currently"+Count+"a"); result =Items[Count--]; System. out. println ("Take away products, currently there"+Count+"a");Notfull. Notify (); } returnResult }
}
The above two methods, one is the producer calls, one is the consumer calls, if the producer and the consumer is a one-to-many relationship, then the deadlock is very likely to occur.

The way to check deadlocks is to look at the execution time of all the steps as infinitely long (mainly related to CPU switching contexts and time slice allocations). Because the Notify method is to give the lock to any one, for example: Consumer a gets notempty, it waits for the notfull lock, and the producer gets notfull, this time the producer releases the Notempty lock, will give the lock to consumer B, The producer itself began to wait for consumer A to release the Notempty lock, thus entering the deadlock state. (a producer, like a consumer, will have a deadlock: it's just not a very high probability)

But if you change to lock implementation:

Public Static Classboundedbuffer{FinalLockLock=NewReentrantlock (); ConditionNotempty=Lock. Newcondition (); ConditionNotfull=Lock. Newcondition ();FinalObject[]Items=NewOBJECT[3];intCount; PublicBoundedbuffer () {Count= 0; }Public voidPut (Object x) {Lock. Lock ();if(Count==2) {Try{System. out. println ("The product library is full.");Notfull. await (); System. out. println ("can add a product, currently has"+Count+"a"); }Catch(Interruptedexception e)
            {E.printstacktrace (); } System. out. println ("To add a product, there is currently"+Count+"a"); ++

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.