JUC:
java.util.concurrent在并发编程中使用的工具类
Lock接口
java官方api中给其的解释:
- Lock implementations provide more extensive locking operations than can be obtained using synchronized methods and statements. They allow more flexible structuring, may have quite different properties, and may support multiple associated Condition objects.
- 锁实现提供了比使用同步方法和语句可以获得的更广泛的锁操作。它们允许更灵活的结构,可能具有非常不同的属性,并且可能支持多个关联的条件对象。
相比于Synchronized的使用,Lock更加灵活和性能
api中的官方案例:
Lock接口的实现 ReentrantLock可重入锁
api中案例:
因为其也是实现Lock接口,所以在使用方法上差不多;Lock的实现类更多的是其锁的特性;
- 可重入锁:A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities.
- 可重入互斥锁,但具有扩展功能。
使用Lock与synchronized差别:
经典案例:多线程卖票小程序
实现步骤:
- 1:创建资源类
- 2:在资源类创建同步方法/同步代码块
synchronized
资源类:
class Ticket{
//30张票
private int number=30;
public synchronized void sale(){
synchronized (this){
}
if (number>0){
System.out.println(Thread.currentThread().getName()
+"\t 卖出"+number--+"号票;还剩下"+number);
}
}
}
使用ReentrantLock重入锁方式:
资源类:
class Ticket{
//30张票
private int number=30;
private Lock lock=new ReentrantLock();
// Lock的实现:可重入锁类:ReentranLock
public void sale(){
lock.lock();
try {
if (number>0){
System.out.println(Thread.currentThread().getName()
+"\t 卖出"+number--+"号票;还剩下"+number);
}
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
买票程序:
public class SaleTicket {
/**
* :三个售票员 卖出三十张票
*
* @Author:LRC
* @Date:11:19 下午 2020/7/2
*/
public static void main(String[] args) throws Exception {
Ticket ticket = new Ticket();
//lambda表达式
new Thread(()->{for (int i = 1; i <=40 ; i++) ticket.sale();},"AA").start();
new Thread(()->{for (int i = 1; i <=40 ; i++) ticket.sale();},"BB").start();
new Thread(()->{for (int i = 1; i <=40 ; i++) ticket.sale();},"CC").start();
}
运行:
(其实运行结果没有意义,因为每次的结果都不一样:
线程启动顺序并不是按代码顺序,因为线程启动是native方法,是看系统的调用)native也就是调用本地库的方法,所以线程的启动顺序不一定和代码顺序是一样的