同步块对象同步方法能更细粒度的锁定内容java
同步锁:太大,容易形成效率低下,过小,锁不住web
线程安全synchronized 尽量锁定合理的范围(不是锁代码,而是锁数据)安全
双重检测并发
package com.wxh.syn; //线程安全synchronized 尽量锁定合理的范围(不是锁代码,而是锁数据) public class Web12306 implements Runnable { int numberKey = 10; boolean flag = true; public static void main(String[] args) { Web12306 web = new Web12306(); new Thread(web,"马超").start(); new Thread(web,"关羽").start(); new Thread(web,"曹操").start(); } public void run() { test7(); } //尽量锁定合理范围,最合理的方法,双重检测 private void test7() { while(flag) { if(numberKey <= 0) { //判断还有没有票 flag = false; return; } synchronized(this) { //由于对象为flag 和numberkey,锁住一个对象是不安全的, if(numberKey <= 0) { //判断临界值,如当只有最后一张票时 flag = false; return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"-->"+numberKey--); } } } private void test5() { while(flag) { synchronized(this) { // a,b,c 三个线程,a拿到锁,进行判断,释放锁,B拿到锁,释放锁,a此时在sleep,B也进入sleep, //但sleep结束,cpu调度可能先执行B,此时就会出现票数同时拿到 if(numberKey <= 0) { flag = false; return; } } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"-->"+numberKey--); } } private synchronized void test3() { while(true) { if(numberKey <= 0) { return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"-->"+numberKey--); } } private void test2() { while(flag) { synchronized((Integer)numberKey) { //由于对象为flag 和numberkey,锁住一个对象是不安全的, if(numberKey <= 0) { flag = false; return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"-->"+numberKey--); } } } private void test() { while(true) { synchronized(this) { //线程安全,由于this对象包括了numberkey和flag if(numberKey <= 0) { return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"-->"+numberKey--); } } } }
银行取钱,锁定银行帐号:app
package com.wxh.syn; /** * synchronized 锁执行完毕以后,才释放锁 * 由于银河存款100,可悲啊取走80后,剩余20不达到happy的他取钱90要求,return * @author Administrator * 代码块:更加精细控制 */ public class UnsafeTest { public static void main(String[] args) { Account1 account = new Account1(170, "结婚礼金"); Drawing1 you = new Drawing1(account, 80, "可悲啊"); Drawing1 wif = new Drawing1(account, 90, "happy的他"); you.start(); wif.start(); } } //建立银行帐户 class Account1{ int money; String name; public Account1(int money, String name) { this.money = money; this.name = name; } } //模拟取款 class Drawing1 extends Thread{ Account1 account; //取钱的帐户 int Outmoney; //取得钱数 int pagemoney; //取得总数 public Drawing1(Account1 account, int outmoney,String name) { super(name); this.account = account; Outmoney = outmoney; } public void run() { test(); } //目标锁定不对,应该锁定对象(银行帐号account) private void test() { if(account.money <= 0) { //提升性能的细节,由于每次线程进来都须要判断锁是否执行完以后再判断 return; //而这一步提早判断当银行余额为0时,不须要执行如下代码,大大提升了并发量。 } synchronized(account) { if(account.money -Outmoney <0) { return; } // try { // Thread.sleep(1000); // } catch (InterruptedException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } account.money -= Outmoney; //帐户余额 pagemoney = Outmoney; System.out.println(this.getName()+"--->帐户余额"+account.money); System.out.println(this.getName()+"--->口袋金额"+pagemoney); } //synchronized 锁执行完毕以后,才释放锁 } }