synchronized 同步方法/块

同步块对象同步方法能更细粒度的锁定内容

 

同步锁:太大,容易造成效率低下,太小,锁不住

线程安全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--);
                }
            
        }
        
            }
        }

 

            银行取钱,锁定银行账号:

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 锁执行完毕之后,才释放锁
        
    }
}


 

转载于:https://my.oschina.net/u/3788977/blog/2051410

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值