juc笔记之synchronized和lock的使用

一、锁是什么?

我们都知道,在多线程的环境下,是会引发线程安全的问题的,那么针对这一问题,java提供了synchronized和lock锁机制来控制线程的并发访问,简单来说锁是用来防止多线程操作同一段资源,以防止出现错误的执行结果。
那下面来讲简单介绍一下两种锁的使用方式吧!

二、使用步骤

1.synchronized

以卖票为例子:

package com.lhh.demo;


/**
 *
 * @param
 * @author HaiHui
 * @date 2021/1/29 10:35
 * @return
 */
public class Tickle1 {
    
    
    private int number = 30;

    public synchronized void sale() {
    
    
        //业务代码
        if (number > 0) {
    
    
        //引入两行代码是为了检测假如不加synchronized会造成怎样的后果。
            System.out.println(Thread.currentThread().getName() + "卖出了" + (number--) + "票,剩余" + number);
            System.out.println(Thread.currentThread().getName());
        }
    }
}

在这里插入图片描述

2.lock

我们还是以卖票为例:

  • 创建ReteenLock对象
  • lock加锁
  • 中间是业务代码
  • unlock解锁
package com.lhh.demo;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
*
*  使用Lock三部曲
 *  1.创建ReteenLock对象
 *  2.lock.lock()  加锁
 *  3.lock.unlock() 解锁
* @author HaiHui
* @date 2021/1/29 10:35
* @param
* @return
*/
public class Tickle {
    
    
    private int number = 30;
    Lock lock = new ReentrantLock();//可重入锁

    public void sale() {
    
    
        lock.lock();/*开启锁*/
        try {
    
    
            //业务代码
            if (number > 0) {
    
    
                System.out.println(Thread.currentThread().getName() + "卖出了" + (number--) + "票,剩余" + number);
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            lock.unlock();/*解锁,必须配对,假如有多个lock.lock()操作,那么就需要多次解锁。*/
        }
    }
}

接下来,我们测试一下卖票的过程:

package com.lhh.demo;

public class TickleDemo {
    
    
    public static void main(String[] args) {
    
    
        //多线程操作统一资源Tickle,并发编程的要求,把tickle资源丢入线程即可。
        Tickle tickle = new Tickle();
        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                tickle.sale();
            }
        }, "A").start();


        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                tickle.sale();
            }
        }, "B").start();

        new Thread(() -> {
    
    
            for (int i = 0; i < 10; i++) {
    
    
                tickle.sale();
            }
        }, "C").start();
    }
}

在这里插入图片描述
声明一点,这里不是按照abc的顺序执行是因为可重入锁ReteenLock的构造方法没有加true参数,默认就是非公平锁,cpu默认随机切换线程执行,如果指定为true的话,那么就是按照严格的顺序执行了,必须是一个线程执行完毕之后释放锁,后面的线程才能被执行。

三、总结

区别:
相同点:

  • 他们都是重入锁
  • 他们都可以用来控制多线程环境下的线程安全问题

不同点:

  • synchronized是一个关键字,而lock是一个java类
  • synchronized无法获取锁的状态,而lock可以做到
  • synchronized可以自动释放锁,而lock需要手动释放,不释放会死锁
  • synchronized适合少量的代码同步代码,而lock释放大量的同步代码
  • synchronized可能引发线程无线等待(拿到锁的线程突然由于某种原因阻塞了,那么造成后面需要该锁的线程一直无限期的等待下去),而lock不一定

猜你喜欢

转载自blog.csdn.net/qq_41486775/article/details/113371688
今日推荐