线程与进程理论知识入门03(类锁,对象锁,显示锁)

synchronized(隐士锁,内置锁)

synchronized 隐士锁(内置锁)(锁定 解锁 看不到)(被JDK封装到内部里面去 原理调用native层跟操作系统交互 完成…)

/**
 * synchronized 隐士锁(内置锁)(锁定 解锁 看不到)(被JDK封装到内部里面去 原理调用native层跟操作系统交互 完成....)
 */
public class GpsEngine {

    private static GpsEngine gpsEngine;
    //单例
    private static GpsEngine getInstance(){
        if(gpsEngine == null){
            //Thread-0 CPU执行权被操作系统调度给释放[暂停]  [获得了cpu执行权 回复] 继续往下走
            gpsEngine = new GpsEngine(); //Thread-1 CPU执行了一次 new ;new 了两次就不是单例了 安全性问题
        }
        return gpsEngine;
    }
    //如果多个线程 或者多个地方调用
    //多线程执行的时候 需要非常注意 安全性问题
}
/**
 * synchronized 隐士锁(内置锁)(锁定 解锁 看不到)(被JDK封装到内部里面去 原理调用native层跟操作系统交互 完成....)
 */
public class GpsEngine {

    private static GpsEngine gpsEngine;
    //单例
    private static synchronized GpsEngine getInstance2(){
        if(gpsEngine == null){
            //Thread-0 此时Thread-1进不来
            gpsEngine = new GpsEngine();
        }
        return gpsEngine;
    }//Thread-0执行完毕
}

类锁:
static synchronized (静态+synchronized 所持有的锁就是这个引擎GpsEngine 的class)
静态代表还没new出来还没有实例化之前就会通过class的方式加载
持有一把锁 GpsEngine.class对象锁 == 类锁

上述代码效率太低,改进一下:

//双重检测 比较典型的单例
//双重检测 比较典型的单例
    public static GpsEngine getGpsEngine() {
        if(gpsEngine == null){

            //Thread-0,Thread-1,Thread-2,Thread-3....都进的来

            //GpsEngine.class对象锁 == 类锁
            synchronized (GpsEngine.class){

                //Thread-0, 此时 Thread-1,Thread-2,Thread-3....进不来

                if(gpsEngine == null){
                    
                    gpsEngine = new GpsEngine();
                }
            }
        }
        return gpsEngine;
    }

对象锁

//多线程执行中,基本上有安全性问题
//加锁
public class SynTest {

    private long count = 0;

    //累加函数
    public void incCount() {
        count ++;
    }

    //线程
    private static class Count extends Thread {

        private SynTest simplOpen;

        public Count(SynTest simplOpen){this.simplOpen = simplOpen;}

        @Override
        public void run() {
            for(int i = 0; i<10000; i++) {
                simplOpen.incCount();// count = count + 10000
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        SynTest synTest = new SynTest();

        //启动两个线程
        Count count1 = new Count(synTest);
        Count count2 = new Count(synTest);
        count1.start();
        count2.start();
        Thread.sleep(50);
        System.out.println(synTest.count);//20000
    }
    
}
14760 //第一次结果
18538 //第二次结果
14289 //第三次结果

加上对象锁

//累加函数
    //synchronized == 对象锁 持有一把锁 SynTest.this SynTest的实例
    public synchronized void incCount() {
        count ++;
    }
20000
public void incCount2(){
        synchronized (this) {//自己去寻找
            count ++;
        }
    }
public void incCount2(){
        synchronized (SynTest.this) {//自己去寻找
            count ++;
        }
    }
20000
//随便持有一把锁, 对象锁 Object对象
    private Object object = new Object();
    private String str = new String();
    public void incCount3(){
        synchronized (object) {//自己去寻找
            count ++;
        }
    }

显示锁

可重入锁 ReentrantLock()
synchronized 天生也是可重入锁
可重入锁就是在递归的时候可反复的拿锁

// synchronized 天生是可重入锁
    //如果synchronized不是可重入锁,无法调用自己 递归第二次第N次无法拿到锁 造成卡死状态一样
    public synchronized void add(){
        count ++;
        add();
    }

ReentrantLock()

//syn 隐士的 内部会完成 锁定 解锁 等等 底层逻辑 我们改不了 看不到,只需要加一个关键字
//Lock 显示锁 我们程序员可以控制 锁定 解锁 等逻辑
public class LockDemo {

    private int count = 0;

    //synchronized 天生也是可重入锁

    //可重入锁 ReentrantLock()
    private Lock lock = new ReentrantLock();

    //多线程执行,如果不加锁,一定存在安全问题
    public void incr() {
        lock.lock(); // 开发者自己锁定
        count ++;  //如果发生异常,后面的无法被解锁别的线程就永远进不来了
        lock.unlock();// 开发者自己去解锁
    }

    public void incr2() {
        lock.lock(); // 开发者自己锁定
        try{
            count ++;
        }finally {//一定会执行finally里面的语句,一定会解锁
            lock.unlock();// 开发者自己去解锁
        }
    }

    // synchronized 天生是可重入锁
    //如果synchronized不是可重入锁,无法调用自己 递归第二次第N次无法拿到锁 造成卡死状态一样
    public synchronized void add(){
        count ++;
        add();
    }
    
    public static void main(String[] args){

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值