public class ProblemClass extends Thread { static int problemcount; private boolean getflag; public ProblemClass(boolean iget) { problemcount = 0; getflag = iget; } public int getcount() { return problemcount; } public void setcount(int x) { problemcount = x; } public void run() { if (getflag) { while (true) { if (problemcount % 2 == 0) { //这里故意做点事情耽搁点时间,制造问题 for (int p = 0; p < 1000; p++) {} //囧rz //------------------------------- int temp = getcount(); System.out.println("获得偶数:" + temp); } } } else { int i = 0; while (true) { //这里故意做点事情耽搁点时间,制造问题 for (int p = 0; p < 1000; p++) {} //囧rz //------------------------------- i++; setcount(i); } } } }public class TestProblem { public TestProblem() { } public static void main(String[] _s){ ProblemClass a = new ProblemClass(true); ProblemClass b = new ProblemClass(false); a.start(); b.start(); } }这个很容易跑出问题来,一大饼的奇数
可以看到如果有线程同时读取,会有问题。 import java.util.Random;public class SyncIssueImpl { private int number = 0;
public void countNumber() { String currentName = Thread.currentThread().getName(); int currentNumber = getNumber(); System.out.println("Thread [" +currentName+"] read number as [" + currentNumber + "]"); currentNumber++;
System.out.println("Thread [" +currentName+"] set number as [" + currentNumber + "]"); setNumber(currentNumber); }
public void setNumber(int newNumber) { String currentName = Thread.currentThread().getName(); System.out.println("Thread [" +currentName+"] set " + "current number [" + this.number + "] to new number [" + newNumber + "]" );
if (this.number >= newNumber) { System.out.println("Thread [" +currentName+"] find error! " + "current number [" + this.number + "] >= new number [" + newNumber + "]" ); throw new RuntimeException("Sync error found!"); } this.number = newNumber; }
public int getNumber() { return this.number; }
/** * */ public SyncIssueImpl() { } /** * @param args */ public static void main(String[] args) { int waitTime = 1; //Minutes int numOfThread = 4; Thread[] threads = new Thread[numOfThread]; final SyncIssueImpl impl = new SyncIssueImpl();
for (int i = 0; i < threads.length; ++i) { threads[i] = new Thread(new Runnable() { @Override public void run() { boolean continued = true; Random rnd = new Random();
不过一个控制get,一个控制set是不会出现问题。为保险,防出问题,你可以加个Synchronized 在get和set的墙面。
这种情况只要多试几次就会出现,或者认为在set线程中加延时
这种情况只要多试几次就会出现,或者认为在set线程中加延时
public class ProblemClass extends Thread {
static int problemcount;
private boolean getflag;
public ProblemClass(boolean iget) {
problemcount = 0;
getflag = iget;
} public int getcount() {
return problemcount;
} public void setcount(int x) {
problemcount = x;
} public void run() {
if (getflag) {
while (true) {
if (problemcount % 2 == 0) {
//这里故意做点事情耽搁点时间,制造问题
for (int p = 0; p < 1000; p++) {} //囧rz
//-------------------------------
int temp = getcount();
System.out.println("获得偶数:" + temp);
}
}
} else {
int i = 0;
while (true) {
//这里故意做点事情耽搁点时间,制造问题
for (int p = 0; p < 1000; p++) {} //囧rz
//-------------------------------
i++;
setcount(i);
}
}
}
}public class TestProblem {
public TestProblem() {
}
public static void main(String[] _s){
ProblemClass a = new ProblemClass(true);
ProblemClass b = new ProblemClass(false);
a.start();
b.start();
}
}这个很容易跑出问题来,一大饼的奇数
import java.util.Random;public class SyncIssueImpl { private int number = 0;
public void countNumber() {
String currentName = Thread.currentThread().getName();
int currentNumber = getNumber();
System.out.println("Thread [" +currentName+"] read number as [" + currentNumber + "]");
currentNumber++;
System.out.println("Thread [" +currentName+"] set number as [" + currentNumber + "]");
setNumber(currentNumber);
}
public void setNumber(int newNumber) {
String currentName = Thread.currentThread().getName();
System.out.println("Thread [" +currentName+"] set "
+ "current number [" + this.number + "] to new number [" + newNumber + "]" );
if (this.number >= newNumber) {
System.out.println("Thread [" +currentName+"] find error! "
+ "current number [" + this.number + "] >= new number [" + newNumber + "]" );
throw new RuntimeException("Sync error found!");
} this.number = newNumber;
}
public int getNumber() {
return this.number;
}
/**
*
*/
public SyncIssueImpl() {
} /**
* @param args
*/
public static void main(String[] args) {
int waitTime = 1; //Minutes
int numOfThread = 4;
Thread[] threads = new Thread[numOfThread];
final SyncIssueImpl impl = new SyncIssueImpl();
for (int i = 0; i < threads.length; ++i) {
threads[i] = new Thread(new Runnable() {
@Override
public void run() {
boolean continued = true;
Random rnd = new Random();
while (continued) {
try {
impl.countNumber();
Thread.sleep(rnd.nextInt() % 60 + 10);
} catch (Exception e) {
continued = false;
}
}
}
}); threads[i].setName("Tester" + i);
}
for (int i = 0; i < threads.length; ++i) {
threads[i].start();
}
try {
for (int i = 0; i < threads.length; ++i) {
threads[i].join(waitTime * 60000);
}
} catch (Exception e) {
System.out.println("error found : " + e);
e.printStackTrace();
}
}
}