GAMES LESSON THREE: Synchronization of Threads

In this applet there are ten threads all accessing the same variables in the applet class. As you would expect these threads take turns working on the variables, but there is no guarantee that they will take turns in the expected way unless you use the synchronized keyword in the portions of code where they are required to take turns. Consider the following method taken from SNYCRO.java:

public void changeXY(int xc, int yc){ x=xc; y=yc; calls++; }
Remember that there are ten threads that all call this method. It is possible for the x value to be updated by one thread while another thread is updating the y value the way it is written. (The CHANGE_XY thread class calls this method and there are ten instances of this thread all going at once.) In reality it doesn't seem that such out of turn behavior is very common, BUT it COULD it happen and so we should re-write this method like this:
public synchronized void changeXY(int xc, int yc){ x=xc; y=yc; calls++; }
This allows only one thread at a time to access this method.

Here is the code for the three classes involved with this sample applet.

SYNCRO.java

// Synchronization Example: import java.awt.*; import java.applet.*; import java.util.*; public class SYNCRO extends Applet { Image offI; Dimension d; int score, calls; int x = 20; int y = 20; int z = 20; CHECK_XY Checker; CHANGE_XY Changer[] = new CHANGE_XY[10]; Color c = Color.blue; public void init(){ d = getSize(); offI = createImage(d.width, d.height); Checker = new CHECK_XY(this); Checker.start(); for(int i = 0; i<Changer.length; i++){ Changer[i] = new CHANGE_XY(this, 100+i*111); Changer[i].start(); } } public void update(Graphics g){ paint(g); } public void changeXY(int xc, int yc){ x=xc; y=yc; calls++; } public void changeZ(){ z*=-1; } public int xValue(){ return x; } public int yValue(){ return y; } public void changeScore(){ score++; } public void changeColor(Color nc){ c = nc; } public void paint(Graphics g){ Graphics offG = offI.getGraphics(); offG.setColor(Color.yellow); offG.fillRect(0,0,d.width,d.height); offG.setColor(c); offG.fillOval(x+100,y+60,40,40); offG.fillOval(300, 60+z, 20,20); offG.drawString("CALLS: " + calls, 20, d.height-50); offG.drawString("SCORE: " + score, 20, d.height-35); offG.drawString("SCORE is the number of times both x and y = 0", 20, d.height-20); offG.drawString("X and Y should never both be zero at the same time.", 20, d.height-5); g.drawImage(offI,0,0,this); } }
CHANGE_XY.java
import java.awt.*; public class CHANGE_XY extends Thread{ SYNCRO app; int delay; CHANGE_XY(SYNCRO s, int d){ app = s; delay=d; } public void run(){ while(true){ if(app.xValue() == 20) app.changeXY(0,20); else app.changeXY(20,0); try{ Thread.sleep(delay); }catch(InterruptedException ie){} } } }
CHECK_XY.java
import java.awt.*; public class CHECK_XY extends Thread{ int x = 20; int y = 0; SYNCRO app; Color COLOR[] = { Color.red, Color.blue, Color.green, Color.magenta }; int i; CHECK_XY(SYNCRO s){ app = s; } public void run(){ while(true){ if(app.x==0 && app.y==0){ app.changeScore(); app.changeColor(COLOR[i]); i++; i=i%COLOR.length; } app.changeZ(); app.repaint(); try{ Thread.sleep(200); }catch(InterruptedException ie){} } } }


ASSIGNMENT: