How Java shares resources

Source: Internet
Author: User
Tags integer resource sleep thread tostring

The

provides built-in mechanisms for a special resource-the memory--java in an object-to prevent conflicts. Since we typically set the data element to be subordinate to the private (private) class, and then access only those memory through a method, you can effectively prevent conflicts by simply setting a specific method to synchronized (synchronized). At any point, only one thread can invoke a synchronized method of a particular object (although that thread can invoke the synchronization method of multiple objects). The simple synchronized method is listed below:
synchronized void F () {/* ... */}
synchronized void g () {/* ... */}
Each object contains a lock (also called Monitor), which automatically becomes part of the object (you do not have to write any special code for this). When any synchronized method is invoked, the object is locked and no other synchronized method of that object can be invoked unless the first method completes its own work and unlocks it. In the example above, if you call F () for an object, you cannot invoke G () for the same object unless F () completes and unlocks. Therefore, all synchronized methods for a particular object share a lock, and this lock prevents multiple methods from writing simultaneously to common memory (for example, multiple threads at the same time).
Each class also has its own lock (as part of the class object), so the synchronized static method can be locked within the scope of a class to prevent contact with static data.
Note If you want to protect some other resources from being accessed by multiple threads at the same time, you can force access to those resources through the synchronized side.

1. Synchronization of counters
with this new keyword, we are more flexible in our approach: you can simply use the Synchronized keyword for the Twocounter method. The following example is a revision of the precedent, with the addition of a new keyword:
 

: Sharing2.java//Using The Synchronized keyword to prevent//multiple access to a particular resource.
Import java.awt.*;
Import java.awt.event.*;

Import java.applet.*;
  Class TwoCounter2 extends Thread {Private Boolean started = false;
  Private TextField T1 = new TextField (5), t2 = new TextField (5);
  Private label L = new label ("Count1 = = Count2");
  private int count1 = 0, count2 = 0;
    Public TwoCounter2 (Container c) {panel p = new Panel ();
    P.add (t1);
    P.add (T2);
    P.add (l);
  C.add (P);
      public void Start () {if (!started) {started = true;
    Super.start ();
      } public synchronized void run () {while (true) {T1.settext (integer.tostring (count1++));
      T2.settext (integer.tostring (count2++));
      try {sleep (500);
    The catch (Interruptedexception e) {}} is public synchronized void Synchtest () {sharing2.incrementaccess ();
  if (count1!= count2) l.settext ("unsynched"); }
Class Watcher2 extends Thread {private Sharing2 p;
    Public Watcher2 (Sharing2 p) {this.p = P;
  Start ();
      public void Run () {while (true) {for (int i = 0; i < p.s.length i++) p.s[i].synchtest ();
      try {sleep (500);
  The catch (Interruptedexception e) {}}} is public class Sharing2 extends Applet {twocounter2[] s;
  private static int accesscount = 0;
  private static TextField acount = new TextField ("0", 10);
    public static void Incrementaccess () {accesscount++;
  Acount.settext (integer.tostring (Accesscount));
  Private Button start = New button ("Start"), observer = New button ("observe");
  Private Boolean isapplet = true;
  private int numcounters = 0;
  private int numobservers = 0;
      public void init () {if (isapplet) {numcounters = Integer.parseint (getparameter ("size"));
    Numobservers = Integer.parseint (GetParameter ("observers")); } s = new Twocounter2[numcounters];
    for (int i = 0; i < s.length i++) s[i] = new TwoCounter2 (this);
    panel p = new Panel ();
    Start.addactionlistener (New Startl ());
    P.add (start);
    Observer.addactionlistener (New Observerl ());
    P.ADD (Observer);
    P.add (New Label ("Access Count");
    P.add (acount);
  Add (P); Class Startl implements ActionListener {public void actionperformed (ActionEvent e) {for (int i = 0; i < S.length;
    i++) S[i].start (); } class Observerl implements ActionListener {public void actionperformed (ActionEvent e) {for (int i = 0; i < numobservers;
    i++) New Watcher2 (sharing2.this);
    } public static void Main (string[] args) {Sharing2 applet = new Sharing2 ();
    This isn ' t a applet, so set the flag and//produce the parameter values from args:applet.isApplet = false;
    Applet.numcounters = (Args.length = = 0 5:integer.parseint (args[0)); Applet.Numobservers = (Args.length < 2 5:integer.parseint (args[1));
    Frame aframe = new Frame ("Sharing2"); Aframe.addwindowlistener (New Windowadapter () {public void windowclosing (WindowEvent e) {SYSTEM.E
        XIT (0);
    }
      });
    Aframe.add (applet, borderlayout.center);
    Aframe.setsize (Applet.numcounters, *100);
    Applet.init ();
    Applet.start ();
  Aframe.setvisible (TRUE); }
} ///:~


We notice that both run () and synchtest () are "synchronized." If only one of these methods is synchronized, the other is free to ignore the object's locking and can be invoked without hindrance. So one important rule to remember is that for all methods of accessing a critical shared resource, you must set them to synchronized, otherwise you won't be able to work properly.
A new problem has now come up. Watcher2 can never see what is going on because the entire run () method is set to "sync." And because of the certainty of running run () for each object, the lock never opens, and synchtest () never gets invoked. The reason for seeing this result is that Accesscount has not changed at all.
One approach we can take to solve this problem is to isolate only a subset of the code in Run (). The part of the code that you want to isolate in this way is called a "critical area", and you use the Synchronized keyword in a different way to set up a critical area. Java provides support for critical areas through a "sync block"; This time, we use the Synchronized keyword to indicate that the lock of the object is used to synchronize the enclosing code. As shown below:

Synchronized (syncobject) {
  //This code can is accessed by only
  //one thread in a time, assuming all
  //Threa DS Respect SyncObject ' s lock
}


The lock must be acquired on the synchobject before it can enter the sync block. If another thread has acquired the lock, the block will not enter and must wait for the lock to be released.
You can remove the Synchronized keyword from the entire run () and replace it with a synchronized block that encloses two key rows, thus completing the modification of the Sharing2 example. But what objects should be used as locks? The object has been marked by synchtest ()-The current object (this)! So the modified run () method looks like this:

  public void Run () {while
    (true) {
      synchronized (this) {
        t1.settext (integer.tostring (count1++));
        T2.settext (integer.tostring (count2++));
      }
      try {sleep
        (+);
      } catch (Interruptedexception e) {}
    }
  }

This is the only modification that must be made to Sharing2.java, and we will see that although two counters will never be out of sync (depending on when watcher is allowed to check them), the watcher is still provided with sufficient access during run () execution.
Of course, all synchronization depends on whether the programmer is diligent: each part of the code to access the shared resource must be encapsulated in an appropriate synchronization block.

2. Efficiency of synchronization
There are two methods to write for the same data, so there's no way to impress people with a high efficiency. It seems that a better approach would be to set all the methods to be automatic synchronization and completely eliminate the synchronized keyword (and, of course, the example containing synchronized run () shows that it does not work well). But it also reveals that acquiring a lock is not a "cheap" solution--the cost of a method call (entry and exit methods, not executing method principals) is at least four times times higher, and this generation is likely to become even more so under our specific current scenario. So if you know a method that doesn't create a conflict, the smartest thing to do is to undo the synchronized keyword.

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.