Multi-thread programming-Practice (2)

Source: Internet
Author: User

This section continues the discussion in the previous section.

[A thread will release the lock on the object after it enters the object Lounge (the wait () method of the object is called)]For this reason. In synchronization, unless necessary, you do not apply the thread. Sleep (long l) method, because the sleep method does not release the object lock.

This is an extremely bad moral character. You do nothing yourself and enter the sleep state, but seize the monitoring lock of the competing object to prevent other threads that need the monitoring lock of this object from running, simply put, it is an act of extreme selfishness. But I have seen manyProgramThe member still calls sleep in the synchronization methodCode.

See the following example:

Package debug; Class sleeptest {public synchronized void wantsleep () {try {thread. sleep (1000*60);} catch (exception e) {} system. out. println ("111");} public synchronized void say () {system. out. println ("123") ;}} class T1 extends thread {sleeptest st; Public T1 (sleeptest st) {This. st = sT;} public void run () {St. wantsleep () ;}} class T2 extends thread {sleeptest st; Public T2 (sleeptest st) {This. st = sT;} public void run () {St. say () ;}} public class test {public static void main (string [] ARGs) throws exception {sleeptest ST = new sleeptest (); New T1 (ST ). start (); New T2 (ST ). start ();}}

We can see that after the instance of thread T1 runs, the current thread grabs the lock of the St instance and then enters sleep. It does not run to system until it has slept for 60 seconds. out. println ("111"); then the run method is completed, and the monitoring lock on the st is released, so that the instance of thread T2.

If we change the wantsleep method:

Public synchronized void wantsleep () {try {// thread. sleep (1000*60); this. wait (1000*60);} catch (exception e) {} system. out. println ("111 ");}

We can see that the thread where the T2 instance is located immediately gets a running opportunity, first prints 123, and the thread where the T1 instance is located is still waiting until 60 seconds after running to system. out. println ("111"); method.

Therefore, calling the wait (long l) method not only blocks the current thread from running within the specified time, but also gives other competing threads a chance to run, how can this benefit not harm yourself? This is also the principle that conscientious programmers should follow.

After a thread calls the wait (long l) method, if the thread continues to run, you cannot know whether it is waiting for time to finish or is awakened by other threads during the wait process, if you are very concerned that it must wait for enough time to execute a task, rather than waiting for it to be awakened halfway, there is a method that is not very accurate:

 
Long L = system. system. currenttimemillis (); wait (1000); // prepare to wait for 1 second for the current thread while (system. system. currenttimemillis ()-l) <1000) // It indicates that it has not waited until 1 second. // It makes other threads wake up wait (1000-(system. system. currenttimemillis ()-l); // wait for the remaining time.

This method is not very accurate, but it can basically achieve the goal.

So in the synchronization method, unless you know exactly what you are doing and want to do so, you have no reason to use sleep. The wait method is enough to achieve your goal. However, if you are a very conservative person, after seeing the above paragraph, you are absolutely disgusted with the sleep method, and are determined not to sleep, so in non-synchronous methods (there are no competing objects with other threads), what should you do if you want the current thread to block for a certain period of time before running? (This is completely a trick. You should apply sleep properly in non-synchronous methods, but if you do not need sleep, do it like this)

 
Public static mysleep (long l) {object o = new object (); synchronized (o) {try {o. Wait (l) ;}catch (exception e ){}}}

Don't worry, no one can call o. Policy [all] outside of this method, so o. Wait (l) will wait until the set time to complete the operation.

[Use of virtual locks]

Simply put, the virtual lock does not call the Synchronized Method (which is equivalent to synchronized (this) or does not call synchronized (this ), in this way, only one thread can run all the threads that call the synchronous methods on this instance. That is to say:

If a class has two Synchronization Methods m1 and m2, only one thread that can call the M1 Method on two or more lines can run, that is, the two calls M1 respectively, only one thread of M2 can run. Of course, there is no competition for non-synchronous methods. The non-synchronous method of this object can be called by any thread after a thread obtains the monitoring lock of this object.

In most cases, this situation may occur. When multiple threads call M1, one resource needs to be protected. When multiple threads call m2, another resource needs to be protected, if we set M1 and M2 as synchronization methods. The two threads that call the two methods respectively do not conflict, but they both need to obtain the Lock of this instance (the synchronous method is to synchronize this), which leads to unnecessary competition.

Therefore, virtual locks should be used here.

The objects protected by M1 and M2 methods are passed in as attributes A1 and A2. Then, the synchronization block for the synchronization method is changed to A1 and A2, respectively, in this way, there will be no competition when different threads call these two methods. Of course, if both M1 and M2 Methods operate on the same protected object, the two methods should still be used as synchronization methods. This is also one of the reasons for synchronizing methods or using synchronization blocks.

 
Package debug; Class sleeptest {public synchronized void M1 () {system. out. println ("111"); try {thread. sleep (10000);} catch (exception e) {}} public synchronized void m2 () {system. out. println ("123") ;}} class T1 extends thread {sleeptest st; Public T1 (sleeptest st) {This. st = sT;} public void run () {St. m1 () ;}} class T2 extends thread {sleeptest st; Public T2 (sleeptest st) {This. st = sT;} public void run () {St. m2 () ;}} public class test {public static void main (string [] ARGs) throws exception {sleeptest ST = new sleeptest (); New T1 (ST ). start (); New T2 (ST ). start ();}}

in this example, we can see that the two threads call the M1 and M2 methods of the St instance respectively, but competition arises because they both need to obtain the st monitoring lock. T2 instances can only run after T1 is completed (10 seconds interval ). Assume that the M1 method needs to operate on a file F1, And the M2 method needs to operate on a file F2. Of course, we can synchronize F1 and F2 in the method, but we do not know F2 yet, whether F2 exists. If it does not exist, we synchronize a null object. We can use the virtual lock:

Package debug; Class sleeptest {string vlock1 = "vlock1"; string vlock2 = "vlock2"; Public void M1 () {synchronized (vlock1) {system. out. println ("111"); try {thread. sleep (10000);} catch (exception e) {}// action F1 }} public void m2 () {synchronized (vlock2) {system. out. println ("123"); // action F2 }}} class T1 extends thread {sleeptest st; Public T1 (sleeptest st) {This. st = sT;} public void run () {St. m1 () ;}} class T2 extends thread {sleeptest st; Public T2 (sleeptest st) {This. st = sT;} public void run () {St. m2 () ;}} public class test {public static void main (string [] ARGs) throws exception {sleeptest ST = new sleeptest (); New T1 (ST ). start (); New T2 (ST ). start ();}}

We can see two threads that call m1 and m2 respectively. Because they obtain the monitoring locks of different objects, they run normally without any competition, only when both threads call M1 or m2 at the same time will blocking occur.

The go deep into Java column is reprinted from axman, A dev2dev user.

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.