Is there an advantage in using synchronization methods instead of synchronization blocks?

Who can give an example of the advantages of synchronization over synchronization block?

#1 building

You can use the reflection API to check synchronization methods. This can be useful for testing some contracts, such as all methods in the model are synchronized.

The following code snippet shows all the synchronization methods for Hashtable:

for (Method m : Hashtable.class.getMethods()) {
        if (Modifier.isSynchronized(m.getModifiers())) {
            System.out.println(m);
        }
}

#2 building

Synchronize with thread. 1) Never use synced (this) in a thread, it doesn't work. Synchronization with (this) uses the current thread as the lock thread object. Since each thread is independent of the others, there is no synchronous coordination. 2) Code tests show that method synchronization does not work in Java 1.6 on the Mac. 3) Synchronized (lockObj), where lockObj is the common shared object of all threads synchronized on it. 4) ReenterantLock.lock() and. unlock() work. See the java tutorial.

The following code shows these points. It also contains A thread safe Vector that will replace the ArrayList to indicate that many threads added to the Vector will not lose any information, while the same threads as ArrayList may lose information. 0) the current code displays the loss of information due to competition conditions A) comment the row currently marked as A, uncomment the row above it, and then run. The method will lose data, but should not lose data. B) Reverse step A, uncomment B and / / end}. Then run to see the results, no data loss C) comment out B, uncomment C. Run, see synchronizing (this) lost data, as expected. There is no time to complete all the variants, I hope it will help you. If synchronization with this or method synchronization is feasible, please indicate the Java and OS versions you tested. Thank you.

import java.util.*;

/** RaceCondition - Shows that when multiple threads compete for resources 
     thread one may grab the resource expecting to update a particular 
     area but is removed from the CPU before finishing.  Thread one still 
     points to that resource.  Then thread two grabs that resource and 
     completes the update.  Then thread one gets to complete the update, 
     which over writes thread two's work.
     DEMO:  1) Run as is - see missing counts from race condition, Run severa times, values change  
            2) Uncomment "synchronized(countLock){ }" - see counts work
            Synchronized creates a lock on that block of code, no other threads can 
            execute code within a block that another thread has a lock.
        3) Comment ArrayList, unComment Vector - See no loss in collection
            Vectors work like ArrayList, but Vectors are "Thread Safe"
         May use this code as long as attribution to the author remains intact.
     /mf
*/ 

public class RaceCondition {
    private ArrayList<Integer> raceList = new ArrayList<Integer>(); // simple add(#)
//  private Vector<Integer> raceList = new Vector<Integer>(); // simple add(#)

    private String countLock="lock";    // Object use for locking the raceCount
    private int raceCount = 0;        // simple add 1 to this counter
    private int MAX = 10000;        // Do this 10,000 times
    private int NUM_THREADS = 100;    // Create 100 threads

    public static void main(String [] args) {
    new RaceCondition();
    }

    public RaceCondition() {
    ArrayList<Thread> arT = new ArrayList<Thread>();

    // Create thread objects, add them to an array list
    for( int i=0; i<NUM_THREADS; i++){
        Thread rt = new RaceThread( ); // i );
        arT.add( rt );
    }

    // Start all object at once.
    for( Thread rt : arT ){
        rt.start();
    }

    // Wait for all threads to finish before we can print totals created by threads
    for( int i=0; i<NUM_THREADS; i++){
        try { arT.get(i).join(); }
        catch( InterruptedException ie ) { System.out.println("Interrupted thread "+i); }
    }

    // All threads finished, print the summary information.
    // (Try to print this informaiton without the join loop above)
    System.out.printf("\nRace condition, should have %,d. Really have %,d in array, and count of %,d.\n",
                MAX*NUM_THREADS, raceList.size(), raceCount );
    System.out.printf("Array lost %,d. Count lost %,d\n",
             MAX*NUM_THREADS-raceList.size(), MAX*NUM_THREADS-raceCount );
    }   // end RaceCondition constructor



    class RaceThread extends Thread {
    public void run() {
        for ( int i=0; i<MAX; i++){
        try {
            update( i );        
        }    // These  catches show when one thread steps on another's values
        catch( ArrayIndexOutOfBoundsException ai ){ System.out.print("A"); }
        catch( OutOfMemoryError oome ) { System.out.print("O"); }
        }
    }

    // so we don't lose counts, need to synchronize on some object, not primitive
    // Created "countLock" to show how this can work.
    // Comment out the synchronized and ending {, see that we lose counts.

//    public synchronized void update(int i){   // use A
    public void update(int i){                  // remove this when adding A
//      synchronized(countLock){            // or B
//      synchronized(this){             // or C
        raceCount = raceCount + 1;
        raceList.add( i );      // use Vector  
//          }           // end block for B or C
    }   // end update

    }   // end RaceThread inner class


} // end RaceCondition outter class

#3 building

As mentioned earlier, when the synchronization function only uses "this", the synchronization block can use user-defined variables as lock objects. Of course, you can work on functional areas that should be synchronized. But everyone says there's no difference between synchronizing a function and using "this" as a lock object for blocks that cover the entire function. This is incorrect, bytecode is generated in both cases. In the case of synchronous blocks, a local variable should be assigned that retains a reference to "this.". As a result, our capabilities are larger (not relevant if you have only a few).

You can find more details about the differences here: http : //www.artima.com/insidejvm/ed2/threadsynchP.html

#4 building

Important note on using synchronization blocks: be careful to use them as locking objects!

The above code snippet from user2277816 illustrates this because a reference to string text is used as a lock object. Realizing that string text is automatically inserted in Java, you should start to see the problem: every piece of code synchronized on the text "lock" shares the same lock! This can easily lead to completely unrelated code deadlocks.

You not only need to be careful with String objects. Boxed primitives are also a danger because the autoboxing and valueOf methods can reuse the same objects based on their values.

For more information, see: https : //www.securecoding.cert.org/confluence/display/java/LCK01-J.+Do+not+synchronize+on+objects+that+may+reused

#5 building

It is often impolite to use locks at the method level. Why lock a piece of code that does not access any shared resources by locking the entire method. Since each object has a lock, you can create virtual objects to achieve block level synchronization. The block level is more efficient because it does not lock the entire method.

Here are some examples

Method level

class MethodLevel {

  //shared among threads
SharedResource x, y ;

public void synchronized method1() {
   //multiple threads can't access
}
public void synchronized method2() {
  //multiple threads can't access
}

 public void method3() {
  //not synchronized
  //multiple threads can access
 }
}

Block level

class BlockLevel {
  //shared among threads
  SharedResource x, y ;

  //dummy objects for locking
  Object xLock = new Object();
  Object yLock = new Object();

    public void method1() {
     synchronized(xLock){
    //access x here. thread safe
    }

    //do something here but don't use SharedResource x, y
    // because will not be thread-safe
     synchronized(xLock) {
       synchronized(yLock) {
      //access x,y here. thread safe
      }
     }

     //do something here but don't use SharedResource x, y
     //because will not be thread-safe
    }//end of method1
 }

[editor]

For Collections such as Vector and Hashtable, they will be synchronized when not using ArrayList or HashMap, and you need to set the sync keyword or call the Collections synchronization method:

Map myMap = Collections.synchronizedMap (myMap); // single lock for the entire map
List myList = Collections.synchronizedList (myList); // single lock for the entire list

Tags: Java Mac IE

Posted on Fri, 07 Feb 2020 04:07:27 -0500 by vinaip