(多线程数据共用的)示例代码:
先来看看“java线程研究---(7)Thread同步:多线程数据共用会产生问题”这篇文章里面主要的代码例子
ShareDataThread.java
package thread; public class ShareDataThread implements Runnable { private int i = 0; @Override public void run() { while (i < 10) { i++; for (int j = 0; j < 10000000l; j++) ; System.out.println(Thread.currentThread().getName() + ": " + i); } } }
OneObjExample.java
package thread; public class OneObjExample { public static void main(String abc[]) { ShareDataThread s1 = new ShareDataThread(); Thread t1 = new Thread(s1); Thread t2 = new Thread(s1); t1.start(); t2.start(); } }
运行结果(其实每次运行结果都不一样的,如下结果只不过是典型的一次结果):
Thread-1: 1
Thread-1: 3
Thread-0: 4
Thread-1: 5
Thread-0: 6
Thread-1: 7
Thread-1: 8
Thread-0: 9
Thread-1: 10
Thread-0: 10
分析运行结果:
我就如上的结果,有如下的分析(或者说猜测,因为多线程这东西,这能根绝现象去揣测,无从得到底这两个线程是如何交替运行的):
- 为什么2没有打印出来?
- thread-1打印1完毕之后,
- thread-1继续执行i++
- thread-1接着执行for循环,由于执行for循环需要较长的时间,
- thread-1还没有来得及打印2,thread-1就被cpu替换下来了。。。
- thread-0开始执行,此时thread-0所拿到的i=2,
- thread-0,在执行i++之后,i=3
- thread-0接着执行for循环,由于执行for循环需要较长的时间,
- thread-0还没有来得及打印3,thread-0就被cpu替换下来了。。。
- thread-1开始执行,此时thread-1所拿到的i=3,
- 注意,此时thread-1是继续上一次他被cpu替换下来的点继续执行,所以
- thread-1直接开始打印3!
- 大家多读读几遍,看看我分析的对不?
- 为什么打印两个10?
- 其实也很好分析
- Thread-1,在要打印之前,被cpu替换下来
- Thread-1再被cpu调用,开始执行的时候,所拿到的i=10。由于是继续上一次代码行号执行,所以
- Thread-1执行打印10。
- Thread-1继续while循环,但是条件不成立,while循环结束,Thread-1进入死亡状态。
- Thread-0,也是在要打印之前,被cpu替换下来
- Thread-0再被cpu调用,开始执行的时候,所拿到的i依旧是10。由于是继续上一次代码行号执行,所以
- Thread-0执行打印10。
- Thread-0继续while循环,但是条件不成立,while循环结束,Thread-0也进入死亡状态。
- 小妹分析的太深入了,有木有
结论总结:
针对于这个示例代码,和打印的结果,综合分析,我的总结就是:
- i++
- for循环
- 打印
- 这三行代码,只要被其他线程进来,分割,侵入,就会造成数据打印不一致的结果。
- 因此,得让这三行代码,具有原子性!不可分割,无法被其他线程进来侵入,打断这三行代码连续执行
- 所以给这三行代码加锁,那么这三行代码就变成了一个整体,具有原子性!
- 好啦,锁的概念,由此诞生!
锁:synchronized
之前的文字,都是为了现在,引入锁的概念,为什么有锁,加锁的目的等。
话不多说,直接看上锁之后的代码
ShareDataThread.java加锁后的修改如下。
package thread; public class ShareDataThread implements Runnable { private int i = 0; @Override public void run() { while (i < 10) { synchronized(this){ // 锁块 i++; for (int j = 0; j < 10000000l; j++); System.out.println(Thread.currentThread().getName() + ": " + i); } } } }
OneObjExample.java 执行类,不变
package thread; public class OneObjExample { public static void main(String abc[]) { ShareDataThread s1 = new ShareDataThread(); Thread t1 = new Thread(s1); Thread t2 = new Thread(s1); t1.start(); t2.start(); } }
运行结果如下:
Thread-1: 1
Thread-1: 2
Thread-1: 3
Thread-0: 4
Thread-0: 5
Thread-1: 6
Thread-1: 7
Thread-0: 8
Thread-0: 9
Thread-0: 10
Thread-1: 11
注意:运行结果,似乎不怎么尽如人意,稍后我会继续完善的。
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-20 09:48:12