您好,欢迎来到爱够旅游网。
搜索
您的当前位置:首页Lock锁、ReentrantLock(可重入锁)使用

Lock锁、ReentrantLock(可重入锁)使用

来源:爱够旅游网

Lock锁

  • jdk 5.0开始,Java提供了更强大的线程同步机制,可以显示定义同步锁对象来实现同步。同步锁使用Lock对象充当。

  • java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前需要先获得Lock对象。

  • ReentrantLock(可重入锁)类实现了Lock,它拥有与sychronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,它可以显示的加锁、释放锁

ReentrantLock(可重入锁)使用

不使用锁,多个线程可能拿到相同票号

package testthread.gaoji;

/**
 * 以买票为例,三个线程操作共同的票资源
 */
public class TestLock {

    public static void main(String[] args) {
        TicketThread ticketThread = new TicketThread();
        Thread thread1 = new Thread(ticketThread, "黄牛");
        Thread thread2 = new Thread(ticketThread, "12306");
        Thread thread3 = new Thread(ticketThread, "美团");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

class TicketThread implements Runnable {

    int ticketNums = 10;

    @Override
    public void run() {
        while (ticketNums > 0) {
            System.out.println(Thread.currentThread().getName() + "获得票号" + ticketNums--);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

输出:

12306获得票号10
黄牛获得票号9
美团获得票号10
12306获得票号8
美团获得票号7
黄牛获得票号6
12306获得票号5
美团获得票号3
黄牛获得票号4
黄牛获得票号2
美团获得票号2
12306获得票号1

加锁后,变成同步的,每次只有一个线程操作代码块

package testthread.gaoji;

import java.util.concurrent.locks.ReentrantLock;

/**
 * 以买票为例,三个线程操作共同的票资源
 */
public class TestLock2 {

    public static void main(String[] args) {
        TicketThread2 ticketThread = new TicketThread2();
        new Thread(ticketThread, "黄牛").start();
        new Thread(ticketThread, "12306").start();
        new Thread(ticketThread, "美团").start();
    }
}

class TicketThread2 implements Runnable {

    volatile int ticketNums = 10;

    //定义Lock锁 为了安全用private final来修饰
    private final ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        try {
            //加锁:一般放在try里边,和需要加锁的方法体一起
            lock.lock();
            while (ticketNums > 0) {
                System.out.println(Thread.currentThread().getName() + "获得票号" + ticketNums--);
                Thread.sleep(0);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //解锁:一般都是finally解锁,确保肯定会执行解锁操作
            lock.unlock();
        }

    }
}

输出:

黄牛获得票号10
黄牛获得票号9
黄牛获得票号8
黄牛获得票号7
黄牛获得票号6
黄牛获得票号5
黄牛获得票号4
黄牛获得票号3
黄牛获得票号2
黄牛获得票号1

synchronized与Lock对比

  • Lock是显示加锁(手动开启和关闭锁,切记要关闭锁),synchronized是隐式锁,出了作用域自动释放
  • Lock只有代码块锁,synchronized有方法锁和代码块锁
  • 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性(提供更多的子类)
  • 优先使用顺序:Lock > 同步代码块(已经进入了方法体,分配了相应资源) > 同步方法(在方法体之外)

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- igbc.cn 版权所有 湘ICP备2023023988号-5

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务