java线程研究---(8)Thread同步:锁的概念

(多线程数据共用的)示例代码:
先来看看“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


分析运行结果:

我就如上的结果,有如下的分析(或者说猜测,因为多线程这东西,只能根据现象去揣测,无从得知底这两个线程是如何交替运行的可怜):

  1. 为什么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!
    • 大家多读读几遍,看看我分析的对不?

  2. 为什么打印两个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



注意:运行结果,似乎不怎么尽如人意,稍后我会继续完善的。






  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值