java 多线程 例子 入门博文一

来源:互联网 发布:网络电视需要机顶盒吗 编辑:程序博客网 时间:2024/06/05 03:57

网上找的一些例子觉得不能说明问题,重写了一个主要来体现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得到了相同的返回结果。

大概就是这样。

原创粉丝点击