您的位置:首页 > 编程语言 > Java开发

java 多线程 例子 入门博文一

2013-07-19 17:03 281 查看
网上找的一些例子觉得不能说明问题,重写了一个主要来体现synchronized的效果



public class TestRunnable implements Runnable {
 private DataCount dataCount = new DataCount();

 public static void main(String[] args) {
  TestRunnable r = new TestRunnable();
  Thread ta = new Thread(r, "Thread-A");
  Thread tb = new Thread(r, "Thread-B");
  Thread tc = new Thread(r, "Thread-C");
  ta.start();
  tb.start();
  tc.start();
 }

 public void run() {
  for (int i = 0; i < 3; i++) {
   System.out.println(Thread.currentThread().getName() + 
   " : 当前dataCount对象的计算值= " + dataCount.count(30));
  }
 }

}
 public class DataCount {
 private int x = 100;

 public int count(int y) {
  x = x - y;
  for (int i = 0; i < 10000000; i++) {
   // 模拟耗时业务
  }
  return x; }
}



输出可能是这样的==============================================================

Thread-A : 当前dataCount对象的计算值= 70

Thread-A : 当前dataCount对象的计算值= 10

Thread-C : 当前dataCount对象的计算值= -50

Thread-C : 当前dataCount对象的计算值= -80

Thread-B : 当前dataCount对象的计算值= -110

Thread-C : 当前dataCount对象的计算值= -140

Thread-B : 当前dataCount对象的计算值= -140

Thread-A : 当前dataCount对象的计算值= -170

Thread-B : 当前dataCount对象的计算值= -170

改写DataCount之后



public class DataCount {
 private int x = 100;

 public int count(int y) {
  synchronized (this) {
   x = x - y;
   for (int i = 0; i < 10000000; i++) {
    // 模拟耗时业务
   }
   return x;
  }
 }
}



输出可能是这样的==============================================================

Thread-A : 当前dataCount对象的计算值= 70 第1次计算

Thread-B : 当前dataCount对象的计算值= 40 第2次计算

Thread-C : 当前dataCount对象的计算值= 10 第3次计算

Thread-A : 当前dataCount对象的计算值= -20 第4次计算

Thread-B : 当前dataCount对象的计算值= -50 第5次计算

Thread-C : 当前dataCount对象的计算值= -80 第6次计算

Thread-A : 当前dataCount对象的计算值= -110 第7次计算

Thread-B : 当前dataCount对象的计算值= -140 第8次计算

Thread-C : 当前dataCount对象的计算值= -170 第9次计算

这个顺序正是我们想要的,不论是哪个线程进行的第3次计算,第3次计算的结果就应该是10,

其他次计算也是要按这个顺序,这时synchronized的效果就看出来了。

接下来对几个现象进行讨论:

1、为什么不用synchronized之前,会出现非我们期望的输出顺序?

2、为什么不用synchronized之前,会出现2次-170,而没有出现-200?

这两个现象其实是同一个问题,

我们来把它的过程梳理一下

这个过程一共有3个线程,每个线程进行了3次计算,一共9次计算。

这9次计算分别是,

Thread-A对x减了3次30,记为TA-1,TA-2,TA-3

Thread-B对x减了3次30,记为TB-1,TB-2,TB-3

Thread-C对x减了3次30,记为TC-1,TC-2,TC-3

这9次计算哪些顺序是必然的?

TA-1一定先于TA-2,TA-2一定先于TA-3

TB-1一定先于TB-2,TB-2一定先于TB-3

TC-1一定先于TC-2,TC-2一定先于TC-3

其他的顺序都是偶然的,可以简单理解为线程内顺序,线程间乱序。

为什么会出现类似

Thread-A : 当前dataCount对象的计算值= 70

Thread-A : 当前dataCount对象的计算值= 10

这样的顺序?

当线程A执行x = x - y;这步操作完成后,可能被其他的线程再次执行x = x - y;然后又切换到线程A执行return x;

这时线程A得到的是两次x = x - y;后的结果,所以第二次返回了10而不是40。

然后解释为什么最后会出现两次-170,而不是在得到-170之后再出现-200呢?

因为一共只有9次计算,也就是最后的结果就是100-30*9=-170。所以不会出现-200。

那为什么会出现连续两次-170呢?线程A执行了x = x - y;之后轮到线程B执行x = x - y;然后轮到线程A执行return x;然后轮到线程B执行return x;

这时A和B得到了相同的返回结果。

大概就是这样。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: