浅谈同步监视器之同步代码块、同步方法
如果有多个线程访问共享资源,可能会出现当一个线程没有处理完业务,然后另一个线程进入,从而导致共享资源出现不安全的情况。
日常例子:银行取钱,A和B有拥有同一个银行账户,A用存折在柜台取钱,B在取款机取钱。取钱有两个关键步骤:
(1)判断账户里的钱的余额是否大于所取钱数
(2)如果大于所取钱数,则账户最终所剩余额 = 余额 - 所取钱数。
如果没有线程同步的情况下,我们假设这一种情况,这个共同的账户里共1000元。
(1)A B同时去取600元,A所在线程执行到上面的第一个步骤,判断所取钱数小于现有余额,CPU时间片用完。
(2)这时B进来到第一个步骤,同样是执行判断,因为A只执行完第一步骤,没有执行减法,这时现有余额还是1000元。
(3)由于在CPU分配的时间里他接着完成了减法操作。这时账户余额为1000 - 600 = 400。成功取出600元。
(4)最后A接着之前执行的步骤,去做减法操作, 账户余额为 -200 = 400 - 600。
到这里,我只想说为什么,是什么银行可以允许你这么做, 当然,除非银行是你家开的。
总之银行不可能让这种情况发生,所以我们的伟大先贤们就想到线程同步,其实很简单,你也能想到。如果让这两个步骤同时完成,不可分开,问题也就迎刃而解。
下面就说到在JAVA中同步代码的实现:
涉及概念:同步监视器,是一个普通的java对象,同一个同步监视器如果一个线程拿到,则其他线程就没有办法拿到。好像是一个房门里只有唯一的一把钥匙, 不能复制。如果一个人拿着它进入房门,其他人只能在外面等候。等他出来你获得了它,你才能进入房间。
下面的代码如果没有做线程同步操作(同步代码块、同步方法、同步锁)结果是如下:
Thread-1------判断所取钱数是否大于余额------
Thread-0------判断所取钱数是否大于余额------
Thread-0======做减法操作,取出现金======
Thread-1======做减法操作,取出现金======
很显然线程1的那两步没有同时完成。
下面的几种方法可以实现两步同时完成。
1、同步代码块:
public class ThreadTest { public static void main(String[] args){Thread t1 = new Thread1(); //线程1Thread t2 = new Thread1();//线程2t1.start();t2.start(); }}class Thread1 extends Thread{ @Override public void run() {super.run();try { BeTested b = new BeTested(); // 这地方,因为这个例子中同步监视器 obj 是线程共享的,两个线程用两个不同的对象,也没有关系,不影响结果。 b.beTested(this);} catch (InterruptedException e) { e.printStackTrace();} }}class BeTested { static Object obj = new Object();; public void beTested(Thread t) throws InterruptedException{synchronized (obj) { // obj 为同步监视器 System.out.println(t.getName() + "------判断所取钱数是否大于余额------"); t.sleep(1000); // 如果没有同步这样能理明显地看到这两步骤不能在一个线程,同一个时间片里执行完成。 System.out.println(t.getName() + "======做减法操作,取出现金======");} }}
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
浅谈同步监视器之同步代码块、同步方法
下载Word文档到电脑,方便收藏和打印~