zoukankan      html  css  js  c++  java
  • syncronized如何上锁

    上锁,根据操作系统所说的原则,对共享变量上锁,对临界区上锁。谁访问临界资源?就给谁上锁

    同步监视器,它上锁的对象。
    1.用关键字给方法上锁
    2.用synchronized代码块上锁

    默认上锁对象:this,指向自身。就是调用这个方法的对象,给他上锁。

    安全的买票(给方法上锁)

    public class SynchronizeTest {
        //线程不安全
        public static void main(String[] args) {
            BuyTicker buyTicker = new BuyTicker();
            new Thread(buyTicker,"lhh").start();
            new Thread(buyTicker,"jhj").start();
            new Thread(buyTicker,"黄牛").start();
        }
    }
    class BuyTicker implements Runnable{
        private int ticketNum = 10;
        boolean flag = true;
        @Override
        public void run() {
            while(flag){//外部停止方式
                try {
                    buy();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }//对买票上锁,锁的this,this是指当前的对象。
        public synchronized void buy() throws InterruptedException {//直接给方法上锁
            //判断是否有票
            if(ticketNum<=0){
                System.out.println(Thread.currentThread().getName()+"票卖完了");
                flag = false;
                return;
            }
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName()+"拿到"+ticketNum--);
        }
    }
    

    安全的银行(给临界区上锁,)

    如果给一个类的方法上锁了,实际上是给this也就是调用方法的这个对象上锁,比如你要是给run()上锁,就相当于你去取钱把银行锁了。但是取钱的人都还在银行里面。所以是要对账户上锁,因为我们逍遥操控的变量就是账户。

    public class UnsafeBake {
        public static void main(String[] args) {
            Account account = new Account("结婚基金",1000);
            Draw you = new Draw(account,50,"你");
            Draw girlFriend = new Draw(account,100,"女朋友");
            you.start();
            girlFriend.start();
        }
    }
    class Account{
        String name;
        int money;
        public Account(String name, int money) {
            this.name = name;
            this.money = money;
        }
    }
    class Draw extends Thread{
        Account account;
        int drawMoney;
        int noMoney;
        public Draw(Account account, int drawMoney, String name) {
            super(name);
            this.account = account;
            this.drawMoney = drawMoney;
        }
        @Override
        public void run() {
            synchronized (account){
                if(account.money-drawMoney<0){
                    System.out.println("余额不足");
                    return;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                account.money = account.money - drawMoney;
                noMoney = noMoney +drawMoney;
                System.out.println(account.name+"余额为:"+account.money);
                System.out.println(this.getName()+"手里的钱"+noMoney);//继承THread可以直接写this
            }
        }
    }
    

    安全的列表

    public class UnsafeList {
        public static void main(String[] args) {
            List<String> list = new ArrayList<String>();
            for (int i = 0; i < 100; i++) {
                new Thread(()->{//lambda表达式
                    synchronized (list){//上锁临界资源list,下面是临界区操作临界资源的代码
                        list.add(Thread.currentThread().getName());
                    }
                }).start();
            }
            try {
                Thread.sleep(1000);//如果不让他睡,程序结束的时候线程也结束了一半了,列表元素就不够100
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(list.size());
        }
    }
    
  • 相关阅读:
    Xcode编译项目出现访问private key提示框
    Mac开机黑屏解决办法
    Mac OS X 系统下快速显示隐藏文件的方法(使用Automator创建workflow)
    cocos2d-x编译错误问题
    解决mac上Android开发时出现的ADB server didn't ACK
    学习笔记之linux下如何调用第三方库的函数接口
    学习笔记之vim的使用
    学习笔记之postgresql
    学习笔记之libevent
    学习笔记之windows 网络编程
  • 原文地址:https://www.cnblogs.com/li33/p/12719179.html
Copyright © 2011-2022 走看看