Java Multi-thread synchronized (ii)

Source: Internet
Author: User

In order to solve the problem of "non-thread-safe", the method used in the previous section is to use the keyword synchronized to modify the methods that multiple threads may access at the same time, but there are some drawbacks to this writing, such as thread A calls a synchronous method modified with synchronized. This method takes a long time to execute, and the other threads must unconditionally wait for thread A to finish releasing the object lock, assuming that the other thread also accesses the synchronization method. This can be solved with synchronized blocks of code. Before I fix it, I'm going to attach a method that wasn't optimized before, so you can see the difference visually.

Prove the disadvantage of the synchronized method, the code is as follows:

public class Entity {public static long begintime1;public static long endtime1;public static long begintime2;public static Long endTime2;}
public class Task_synchronized {private String       Getdata1;private String GetData2;  //two child threads to invoke public methods   publicly  synchronized   void  dolongtimetask ()   {try {System.out.println ("Begin Task") ; Thread.Sleep (3000); 
//getdata1 and getdata2 can actually be two very time-consuming operations in the process, so that the effect is renamed GETDATA1 = "value returned from remote after long processing Task 1 threadname=" + thread.currentthread (). GetName (); getData2 = "value returned from remote after long processing Task 2 Threadname= "+ thread.currentthread (). GetName (); System.out.println (GETDATA1); System.out.println (GETDATA2); SYSTEM.OUT.PRINTLN ("End Task");} catch (Interruptedexception e) {e.printstacktrace ();}}}
public static void Main (string[] args) throws Interruptedexception {task_synchronized Task = new task_synchronized (); MyThread1 T1 = new MyThread1 (Task); T1.start (); MyThread2 t2 = new MyThread2 (Task); T2.start (); Thread.Sleep (10000);//Because thread 1 and thread 2 which do not necessarily, so compare the time, the beginning of time to take a smaller value, the end of the time to take a larger value long BeginTime = Entity.begintime1;if ( Entity.begintime2 < entity.begintime1) {beginTime = entity.begintime2;} Long endTime = entity.endtime1;if (Entity.endtime2 > entity.endtime1) {endTime = entity.endtime2;} SYSTEM.OUT.PRINTLN ("Time consuming" + (endtime-begintime)/+ + "s");}//First threadpublic static class MyThread1 extends Thread {private task_synchronized task;public MyThread1 (task_synchronized Task) {su Per (); this.task = task;} @Overridepublic void Run () {super.run (); entity.begintime1 = System.currenttimemillis ();Task.dolongtimetask ();entity.endtime1 = System.currenttimemillis ();}}//A second threadpublic static class MyThread2 extends Thread {private task_synchronized task;public MyThread2 (task_synchronized Task) {su Per (); this.task = task;} @Overridepublic void Run () {//TODO auto-generated method Stubsuper.run (); Entity.begintime2 = System.currenttimemillis ();Task.dolongtimetask ();Entity.endtime2 = System.currenttimemillis ();}}   

the results of the operation are as follows: task_synchronized class can be seen, Synchronized decorated is the Dolongtimetask () method, from the execution of the results can also be seen syschronized adornment method execution order is this: thread- 0 must be synchronized method all finished, after releasing the object lock, Thread-1 can execute, that is, no matter which line enters upgradeable grab on the CPU, it is necessary to execute after the end, another thread can be executed on the CPU, so that the time to execute down is 6s.

          So next look at how to solve this problem with synchronized code block, I wrote an example, as follows:

 public class Task_synchronized {private String       Getdata1;private String GetData2;  //no synchronized adornments   public void  dolongtimetask ()   {try {System.out.println ("Begin task"); Thread.Sleep (3000); String privateGetData1 = "long-handled task 1 threadname=" + thread.currentthread (). GetName (); String privateGetData2 = "long-handled task 1 threadname=" + thread.currentthread (). GetName (); 
//synchronized code block synchronized (this) {getData1 = Privategetdata1;getdata2 = PrivateGetData2;} System.out.println (GETDATA1); System.out.println (GETDATA2); SYSTEM.OUT.PRINTLN ("End Task");} catch (Interruptedexception e) {e.printstacktrace ();}} }

   The execution result is as follows: only need to modify Dolongtimetask () This method, with synchronized code block instead of synchronized modification method, from the running result can see time only 3s, time shortened is due to thread thread- 0 when accessing the Task_synchronized class's synchronization code block, thread Thread-1 can still access the non-synchronous methods in the Task_synchronized class. Why do you think about synchronizing variables getData1 and getData2 here, I said before about "non-thread-safe", one of the reasons is that there may be a "dirty read" when multiple threads are accessing member variables at the same time.

But there are two more questions to verify: is the content in the syschronized code block really synchronous? Does this this really represent the object lock of the current class? Below I have written an example to verify the following:

public static void Main (string[] args) {Task task = new Task (); Threada a = new Threada (Task); A.setname ("a"); THREADB B = new threadb (Task), B.setname ("B"); A.start (); B.start ();} public static class Threada extends Thread {private task Task;public Threada (Task Task) {super (); this.task = Task;} @Overridepublic void Run () {super.run ();Task.dolongtimetask ();}}public Static class Threadb extends Thread {private Task task;public threadb (Task Task) {super (); this.task = Task;} @Overridepublic void Run () {super.run ();Task.dolongtimetask ();}}}class Task {public voidDolongtimetask (){for (int i = 0; i < i++) {System.out.println ("nosynchronized threadname=" + thread.currentthread (). GetName () + "I = "+ (i + 1));} System.out.println ("*********************************");synchronized (this){for (int i = 0; i < i++) {System.out.println ("Synchronized threadname=" + thread.currentthread (). GetName () + "i=" + (i + 1));}}}

The results of the operation are as follows: As can be seen from figure (a), two threads perform the first for loop, which is not synchronous, as shown by Figure B1, B2, C1, c2, thread A is executed, thread B starts executing, so the synchronized code block is synchronous.

figure (a) figure (B1) figure (B2)

   Figure (C1)        figure (C2)

So how to verify that the object monitor used by synchronized is one, that is, this represents the object lock of the current class. It is necessary to prove that only one thread is releasing the current object lock and other threads can execute it. I have written an example, as follows:

public static void Main (string[] args) {MyService service = new MyService (); Threada a = new Threada (service); A.setname ("a"); THREADB B = new threadb (service), B.setname ("B"); A.start (); B.start ();} public static classThreadaExtends Thread {private MyService service;public Threada (MyService service) {super (); this.service = Service;} @Overridepublic void Run () {super.run ();Service.servicemethoda ();}}public Static ClassthreadbExtends Thread {private MyService service;public threadb (MyService service) {super (); this.service = Service;} @Overridepublic void Run () {super.run ();Service.servicemethodb ();}}}class MyService {public voidServicemethoda (){synchronized (this){try {System.out.println ("A begin Time=" + system.currenttimemillis ());Thread.Sleep (the);System.out.println ("A end Time=" + System.currenttimemillis ());} catch (Interruptedexception e) {e.printstacktrace ();}}} public voidServicemethodb (){synchronized (this){try {System.out.println ("B begin Time=" + system.currenttimemillis ());Thread.Sleep (+);System.out.println ("B end Time=" + System.currenttimemillis ());} catch (Interruptedexception e) {e.printstacktrace ();}}}
    The result of the operation is as follows: From the code can be seen, two synchronized code block has a sleep method, but does not affect the execution order of the thread, if the two this is not the same lock object, then during the period of sleep, the thread will certainly appear alternately, from the results can be seen, After thread A executes, thread B starts executing, stating that thread B's access to the synchronized block Servicemethodb is blocked when thread a accesses MyService's synchronous code block Servicemethoda. So the object monitor is the same.

Java Multi-thread synchronized (ii)

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.