Lock锁实现线程安全

Lock锁实现线程安全

在Java1.5之前,只能使用synchronized关键字和volatile关键字协调共享对象的访问,Java1.5之后,提供了lock接口,更加的灵活方便。

ReentrantLock 实现了 Lock 接口,并提供了与 synchronized 相同的互斥性和内存可见性。但相较synchronized 提供了更高的处理锁的灵活性。

值得注意地方:

  1. 加锁后一定要记得解锁;
  2. 解锁的位置一定要放在finally里面;

使用lock模拟卖票,保证票数一致:

package leo.lockTest;

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

public class LockTest {
    public static void main(String[] args) {
        TicketThread ticketThread = new TicketThread();
        new Thread(ticketThread, "窗口1").start();
        new Thread(ticketThread, "窗口2").start();
        new Thread(ticketThread, "窗口3").start();
    }
}

/**
 * 场景:多窗口卖票
 * 拟达到的目标:
 * 1.多窗口同时卖票,所以每个窗口都可以卖出去,不能只在一个窗口卖完了;
 * 2.票数要一致,不能多卖不能少卖;
 * 3.票卖完后,所有窗口关闭,不浪费资源。
 */
class TicketThread implements Runnable {

    int ticket = 100;
    private Lock lock = new ReentrantLock();

    @Override
    public void run() {
        // 这个循环只是保证,没有余票就结束循环
        while (ticket > 0) {
            // 锁住
            lock.lock();
            try {
                // 一定要在锁里面对ticket做余票判断
                if (ticket > 0) {
                    try {
                        Thread.sleep(1);
                        System.out.println(Thread.currentThread().getName() + "售出票后还剩:" + --ticket);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } finally {
                // 一定要在finally里面释放锁
                lock.unlock();
            }
        }
        return;
    }
}

执行结果:
Lock锁实现线程安全_第1张图片

你可能感兴趣的:(JUC)