2、Lock接口

2.1 Synchronized关键字

介绍

Synchronized 是 Java 中的关键字,是一种同步锁。

Synchronized 作用范围

1.修饰一个代码块:被修饰的代码块称为同步语句块,其作用的范围是大括号括起来的代码,作用的对象是调用这个代码块的对象。

public class Test2 {
    public void test(){
        //同步代码块
        synchronized (this){
            
        }
    }
}

2.修饰一个方法:被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;。

public class Test2 {
    //同步方法
    public synchronized void test(){
    
    }
}

3.修改一个静态的方法:其作用的范围是整个静态方法,作用的对象是这个类的所有对象。

public class Test2 {
    //静态同步方法
    public static synchronized void test(){

    }
}
  1. 修改一个类,其作用的范围是synchronized 后面括号括起来的部分,作用的对象是这个类的所有对象。
class ClassName {
   public void method() {
      synchronized(ClassName.class) {
      }
   }
}

多线程的编程步骤

第一步:创建资源类,在资源类中创建属性和方法。

第二步:创建多个线程,调用资源类的操作方法。

Synchronized 实现卖票案例

需求

3个卖票员,卖出30张票。

分析

资源类是:票;属性是:30;方法是:卖;3个卖票员是三个线程。

代码实现

package com.ae.juc.sync;

//第一步:创建资源类,在资源类中创建属性和方法。
class Ticket{
    //定义属性:票数
    private int number = 30;
    //方法:卖票
    public synchronized void sale(){
        if(number > 0){
            System.out.println("线程 "+Thread.currentThread().getName()+ " 卖出 "+ (number--) + " 剩下 "+number);
        }
    }
}

public class SaleTicket {
    public static void main(String[] args) {
        //第二步:创建多个线程,调用资源类的操作方法。
        final Ticket ticket = new Ticket();

        //创建三个线程
        new Thread(new Runnable() {
            public void run() {
                //调用卖票方法
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            }
        },"aa").start();

        new Thread(new Runnable() {
            public void run() {
                //调用卖票方法
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            }
        },"bb").start();

        new Thread(new Runnable() {
            public void run() {
                //调用卖票方法
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            }
        },"cc").start();
    }
}

总结

Synchronized可以实现自动实现上锁和释放锁。

2.2 什么是Lock接口

Lock的介绍

Lock锁实现提供了比使用同步方法(Synchronized)和语句可以获得的更广泛的锁操作。它们允许更灵活的结构,可能具有非常不同的属性,并且可能支持多个关联的条件对象。Lock提供了比 synchronized更多的功能。卜

Lock 与的Synchronized区别

  • Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个类,通过这个类可以实现同步访问;·
  • Lock和synchronized有一点非常大的不同,采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized 代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。·

Lock 和 synchronized 有以下几点不同

1. Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现。

2. synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;。

3. Lock可以让等待锁的线程响应中断,而synchronized 却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;。

4.通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。

5. Lock 可以提高多个线程进行读操作的效率。

2.3 创建线程的多种方式

  • 继承Thread类
  • 实现Runnable接口
  • 使用Callable接口
  • 使用线程池

2.4 使用Lock实现卖票例子

package com.ae.juc.lock;

import java.util.concurrent.locks.ReentrantLock;

//第一步:创建资源类,在资源类中创建属性和方法。
class Ticket{
    //定义属性:票数
    private int number = 30;

    //创建一个可重入锁
    private final ReentrantLock lock = new ReentrantLock();
    
    //方法:卖票
    public void sale(){
        //上锁
        lock.lock();
        try {
            if(number > 0){
                System.out.println("线程 "+Thread.currentThread().getName()+ " 卖出 "+ (number--) + " 剩下 "+number);
            }
        }finally {
            //解锁
            lock.unlock();
        }
    }
}

public class SaleTicket {
    public static void main(String[] args) {
        //第二步:创建多个线程,调用资源类的操作方法。
        final Ticket ticket = new Ticket();

        //创建三个线程
        new Thread(new Runnable() {
            public void run() {
                //调用卖票方法
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            }
        },"aa").start();

        new Thread(new Runnable() {
            public void run() {
                //调用卖票方法
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            }
        },"bb").start();

        new Thread(new Runnable() {
            public void run() {
                //调用卖票方法
                for (int i = 0; i < 40; i++) {
                    ticket.sale();
                }
            }
        },"cc").start();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

了凡啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值