多线程并发之对synchronized和Lock的简单使用

比如有三个线程thread-0,  thread-1,  thread-3

三个线程同时在执行一个带锁的方法时,如果thread-0先获得了锁,那么其它二个线程就只能外面等着,直到thread-0把锁给释放了,这个时候就由其它线程去争取这个锁.

生活中的例子: 现在有三个人同时都要上厕所A,B,C . A先进入到了厕所,这个时候A就会把门给锁了,B,C就要在外面等,直到A上完出来把门打开,这个时候B,C才能有一个人进去,进去后也是锁门,出来也是解锁,然后继续下一个人.

锁可以解决多线程中线程安全的问题.

在android中的单例(懒汉式)

public class SingleTon {
    private static SingleTon sInstance;

    public static SingleTon getInstance() {
        if (sInstance ==null) {
            //1:
            sInstance = new SingleTon();
        }
        return sInstance;
    }
}

如果多线程调用这个getInstance的话就会有问题,下面分析一下

同样有三个线程: thread-0, thread-1, thread-2

注释1处: 假如thread-0执行到1处时候cpu执行器被操作系统调度给释放了,这时thread-1进来了,发现sInstance是空的,就会执行下new代码,最后执行完了,这个时候thread-0恢复了获得了cpu执行权,thread-0也new出了一个,这样这个sInstance被创建了二次,就会引发安全性问题

解决方法,加synchronized锁住,被称之为隐式锁,因为加锁解锁我们都看不到,是内部自己完成的.

public class SingleTon {
    private static SingleTon sInstance;


    public synchronized static SingleTon getInstance() {
        if (sInstance ==null) {
            sInstance = new SingleTon();
        }
        return sInstance;
    }
}

synchronized使用方法

作用在静态方法之上执行的是一个类锁xxx.class

作用在非静态方法之上执行的是当前的对象锁Object object;

上面那个写法会有性能问题,因为每个线程都会在方法外等待,所以性能不是非常好,改进版本

public class SingleTon {
    private static SingleTon sInstance;


    public static SingleTon getInstance() {
        if (sInstance == null) {
            synchronized (SingleTon.class) {
                 if (sInstance == null) {
                     sInstance = new SingleTon();
                 }
                
            }
        }
        return sInstance;
    }
}

这二种方法执行的锁其实是同一个锁

这里再多提一嘴静态方法的synchronized和非静态方法的区别

public class SingleTon {
    private static SingleTon sInstance;


    public synchronized static SingleTon getInstance() {
        if (sInstance ==null) {
            sInstance = new SingleTon();
        }
        return sInstance;
    }
}

public class SingleTon {
    private static SingleTon sInstance;


    public static SingleTon getInstance() {
        synchronized(SingleTon.class){
       
            if (sInstance ==null) {
                sInstance = new SingleTon();
            }
        }

        return sInstance;
    }
}

上面二个方法是等价的

public class SingleTon {
    private static SingleTon sInstance;


    public synchronized SingleTon getInstance() {
        if (sInstance ==null) {
            sInstance = new SingleTon();
        }
        return sInstance;
    }
}

public class SingleTon {
    private static SingleTon sInstance;

    public SingleTon getInstance() {
        synchronized(this){
       
            if (sInstance ==null) {
                sInstance = new SingleTon();
            }
        }

        return sInstance;
    }
}

这上面二个方法也是等价的

 

显示锁 Lock: 我们程序员可以自己控制

在下面这个demo中可以发现在二个线程都执行add这个方法的时候会出现线程安全问题,解决方法有二种

1:在方法上加个synchronized,第二种方法使用Lock这个来操作加锁解锁,  synchronized天生是可重入锁

public class LockDemo {
    private int mCount = 0;
    private Lock mLock = new ReentrantLock();//这是一个可重入锁

    public void add() {//有问题
        mCount++;
    }
    
    public void add() {//没问题
        mLock.lock();//自己加锁
        mCount++;//如果这里发生异常,下面就不会解锁,就会导致所有线程都进不来
        mLock.unlock();//自己解锁
    }
    public void add() {//没问题
        try {
            mLock.lock();
            mCount++;
        }finally {
            mLock.unlock();
        }
      
    }

    public synchronized void add() {//没问题
        mCount++;
    }

    private static class MyThread extends Thread {
        LockDemo mLockDemo;

        public MyThread(LockDemo lockDemo) {
            mLockDemo = lockDemo;
        }

        @Override
        public void run() {
            super.run();
            for (int i = 0; i < 10000; i++) {
                mLockDemo.add();
            }
        }
    }

    public static void main(String[] args) {

        LockDemo lockDemo = new LockDemo();
        new MyThread(lockDemo).start();
        new MyThread(lockDemo).start();
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("count: " + lockDemo.mCount);
    }

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值